转自: https://blog.smartlogic.io/elixir-dynamic-supervisors/

I have been working on my side project Grapevine, a community site for text based multiplayer games (MUDs.) The existing games primarily have a telnet interface for playing. This generally involves using a local client or hoping the game provides a web client for you. So I've been working on a general purpose client that any game can use. You can see it in action for my game MidMUD.

This involves a new web client that uses Phoenix Channels to spin up a backing :gen_tcp process. This process is started inside of a DynamicSupervisor, a new feature introduced in Elixir 1.6. We place the process inside of the supervisor to keep the process alive across page reloads. Lets see how it works!

Basic Flow

When a new web client starts they join a channel named play:client. The channel ensures that the game they are trying to connect to exists and starts the backing process.

{:ok, pid} = WebClient.connect(socket.assigns.user,
game_id: socket.assigns.game.id,
host: connection.host,
port: connection.port,
channel_pid: socket.channel_pid
)

This Client process starts itself inside of a DynamicSupervisor as a transientprocess and saves the calling channel PID in order to forward any received data to the front end. This uses the DynamicSupervisor.start_child/2 function.

def start_client(callback_module, opts) do
spec = {Client, [module: callback_module] ++ opts}
DynamicSupervisor.start_child(__MODULE__, spec)
end

Once the Client process is alive it parses the telnet stream and forwards any text directly to the web front end.

Handling Page Reloads

The Client process is globally registered with the user's ID and the game's ID as part of the name, {:webclient, {1, 1}}. With this, we can check :global to see if the process already exists before starting a new process. If the process exists we overtake the Client process with our new channel.

def connect(user, opts) do
case :global.whereis_name(pid(user, opts)) do
:undefined ->
ClientSupervisor.start_client(__MODULE__, opts ++ [name: {:global, pid(user, opts)}]) pid ->
set_channel(pid, opts[:channel_pid])
{:ok, pid}
end
end

set_channel/2 sends a message to the process which sets the internal channel_pid state for forwarding text to the web client.

Conclusion

With this setup I'm able to have a place to supervise Client processes and allow for session "stickiness" on page reloads. The DynamicSupervisor will delete the child_spec of the Client process after it terminates with a :normal reason. Otherwise the process will be restarted allowing for minor hiccups in the network.

All of this code is open source on GitHub, check out the Grapevine repo. I also worked on this during my Elixir live coding stream. I'll be back doing more live coding on that channel every Monday from 12PM-1PM Eastern.

 
 
 
 

Using Elixir Dynamic Supervisors的更多相关文章

  1. [Erlang 0108] Elixir 入门

    Erlang Resources里面关于Elixir的资料越来越多,加上Joe Armstrong的这篇文章,对Elixir的兴趣也越来越浓厚,投入零散时间学习了一下.零零散散,测试代码写了一些,Ev ...

  2. 基于Erlang VM的函数式编程语言Elixir

    Elixir官网:http://elixir-lang.org/ Elixir是一种函数式动态语言,用于构建可伸缩.易维护的应用程序. Elixir是基于Erlang VM的,其广为人知的特点是运行低 ...

  3. Elixir游戏服设计四

    上章说到我们要引入syn https://github.com/ostinelli/syn/ 看过文档,它并没有直接提供{via, Module, Name} 相关的方法.我们需要封装一下. Name ...

  4. Elixir游戏服设计三

    玩家进程用gen_server来建模,我不直接使用 use GenServer, 而是使用exactor,该库可以去掉反锁的接口定义. 我们新建一个 player_server_manager app ...

  5. Connecting Elixir Nodes with libcluster, locally and on Kubernetes

    转自:https://www.poeticoding.com/connecting-elixir-nodes-with-libcluster-locally-and-on-kubernetes/ Tr ...

  6. Install Erlang and Elixir in CentOS 7

    In this tutorial, we will be discussing about how to install Erlang and Elixir in CentOS 7 minimal s ...

  7. PatentTips - Systems, methods, and devices for dynamic resource monitoring and allocation in a cluster system

    BACKGROUND  1. Field  The embodiments of the disclosure generally relate to computer clusters, and m ...

  8. var和dynamic的区别

    1.var 1.均是声明动态类型的变量. 2.在编译阶段已经确定类型,在初始化的时候必须提供初始化的值. 3.无法作为方法参数类型,也无法作为返回值类型. 2.dynamic 1.均是声明动态类型的变 ...

  9. 遍历dynamic的方式

    一.遍历ExpandoObject /// <summary> /// 遍历ExpandoObject /// </summary> [TestMethod] public v ...

随机推荐

  1. CSS--思维导图

    CSS--思维导图

  2. [Leetcode221]最大面积 Maximal Square

    [题目] Given a 2D binary matrix filled with 0's and 1's, find the largest square containing only 1's a ...

  3. java构造函数使用方法总结 (继承与构造函数)

    使用构造器时需要记住: 1.构造器必须与类同名(如果一个源文件中有多个类,那么构造器必须与公共类同名) 2.每个类可以有一个以上的构造器 3.构造器可以有0个.1个或1个以上的参数 4.构造器没有返回 ...

  4. day 71-72 cookie 和session

    拓展知识   request---->请求信息 属性: request.path       # 获取访问文件路径 request.method属性 #获取请求中使用的HTTP方式(POST/G ...

  5. 漫步Java------接口

    接口 一.定义 具有相同行为(方法),但是不相关的类 二.特点 只是提供方法,不定义方法的具体实现. 一个类只能继承一个父类,但是接口却可以继承多个接口. 接口是一个引用类型的变量 接口没有构造方法, ...

  6. uniGUI HyperServer

    uniGUI HyperServer 是一种新的服务器体系架构, 旨在高度提高 uniGUI 应用程序的可用性.稳定性和特定的可伸缩性. 这一目标是通过应用业界已知和广泛使用的技术 (如负载平衡和过程 ...

  7. python 递归函数操作方法

    .递归 是指函数/过程/子程序在运行过程序中直接或间接调用自身而产生的重入现象.在计算机编程里,递归指的是一个过程:函数不断引用自身,直到引用的对象已知.使用递归解决问题,思路清晰,代码少.但是在主流 ...

  8. 2019-03-07-day006-小数据池

    01 昨日内容回顾 字典: 映射,{} 键值对的形式存储,容器型数据类型,key 唯一的,可哈希的,value任意数据类型,对象. 3.6之前无序的, 3.6之后,有序的(第一次创建字典的顺序) 特点 ...

  9. http状态码301和302的区别

    1.官方的比较简洁的说明: 301 redirect: 301 代表永久性转移(Permanently Moved) 302 redirect: 302 代表暂时性转移(Temporarily Mov ...

  10. 河南省第四届ACM省赛(T3) 表达式求值

    表达式求值 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近又学会了一些简单的函数求值,比如,它知道函数min ...