What is the best way to share state between phoenix channels?

We have one process per phoenix channel, so every channel has its own isolated state. A user may join multiple different channels and in some circumstances some state needs to be shared between them. What is the idiomatic way to read and write user data between his channels: ETS, Agent, etc?

1 Like

Question is why you want to share a state between different channels?
Ideal solution is to have totally isolated channels, so whatever you need in one channel, you do in the scope of this channel.
Choosing between ETS, Agent or GenServer is basically matter of what you like - the most explicit and flexible way to customize how you want to interact with the “storage” is GenServer.

1 Like

What I do is maintain state in one agent per channel. I have “registry” like in http://elixir-lang.org/getting-started/mix-otp/supervisor-and-application.html, which is a genserver process, that starts/stops these agents: name and pid are stored in an ets table. Furthermore part of the state of the agents is maintained in ets in that registry. This info is used in another channel. See the picture below. The grids show info of the different agents, in the screen above another channel is used wherein the state of one agent is maintained via a workflow (info about that workflow is available in the agent).

3 Likes

This turns out to be a generally hard problem if you’re running multiple instances. A single user could have multiple tabs open and one tab could have a channel process on server A and the other tab could have a channel process on server B, and now you’ve got a distributed database problem.

Phoenix.Presence provides some basic capabilities around presence meta-data tracking IIRC based on CRDTs. If that isn’t good enough your next steps sort of depend on what properties you want.

3 Likes

@ibarch: Did you read my question?
What I done in one project is separate user actions (login, register, logout …) and other logic. I generated Token for user.id and send it to client. Then client sends when connecting to other channels and finally server-side in join method I verified token and searched for user with id from result and assigned it to channel.
To keep session I saved token in cookies and send it to users channel also when joining, so all join methods have call to module to verify, find, fetch user data and assign them to channel.

1 Like