转自: 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. 哈希表概念和实现,C/C++实现

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  2. 4.6 C++抽象基类和纯虚成员函数

    参考:http://www.weixueyuan.net/view/6376.html 总结: 在C++中,可以通过抽象基类来实现公共接口 纯虚成员函数没有函数体,只有函数声明,在纯虚函数声明结尾加上 ...

  3. pssac plot

    for multi-waveforms with different colors: R-Xmin/-Xmax/Ymin/Ymax -Ba/b, a: x delta; b:y delta -MYma ...

  4. CodeForces ~ 996

    Allen has a LOT of money. He has nn dollars in the bank. For security reasons, he wants to withdraw ...

  5. 实力封装:Unity打包AssetBundle(番外篇)

    前情提要:第二种打包方式. 自定义AssetBundle包扩展名 在之前的教程中,我们已经多次提到过扩展名了,并且也已经说明了如何设置自定义的AssetBundle扩展名.至于为什么还要把它单独拿出来 ...

  6. C#窗体的浮动及隐藏

    using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...

  7. IE6以下版本对元素width和height的处理与CSS标准的兼容性问题

    1.CSS使用width和height定义元素框的内容,Windows平台的IE6以下版本浏览器并未按照标准处理而是使用width和height来定义可见元素框的尺寸,IE/win使用width来描述 ...

  8. 如何让你的 React Native 应用在键盘弹出时优雅地响应

    原文地址:How to make your React Native app respond gracefully when the keyboard pops up 原文作者:Spencer Car ...

  9. Go parameter passing

    package main import ( "fmt" ) func main() { fmt.Println("Hello, playground") var ...

  10. 【Leetcode】292. Nim Game

    problem 292. Nim Game solution class Solution { public: bool canWinNim(int n) { ; } }; 来generalize一下 ...