rms.mrcs
PhonixLiveState - shared state across LiveViews and Controllers
Hi there ![]()
Just dropping by to share PhonixLiveState, a lib I’ve just published.
It’s still VERY RAW, but already in a reasonably usable state.
The idea is to define a state in a process separate from the liveview, which enables some interesting features:
-
Easier to isolate information in a state
-
Auto recovery in case the liveview crashes
-
Share states between liveviews within the cluster
-
Share state between a Phoenix Controller and a LiveView
-
Once connected, you can access your shared state in the template with
@live_assigns -
Yes, the assign is automatically updated when any client makes a change
On top of that, I added a few extra features:
-
Auto shutdown with TTL (configurable) when no clients are connected: prevents zombie processes
-
Read/write permissions with ACL for group/public
Keep in mind that it was originally built to fulfill my own needs on another project, so it might not fit perfectly into your workflow (but I tried my best to keep it use-case agnostic).
Any feedback is more than welcome!
Thanks!!
Most Liked
Asd
Good idea, well documented and written code. While I was reading the code, I discovered these questions/issues:
use PhoenixLiveState, :clientis essentially a noop. It raises no error, but it also exports no hooks or anything. Why?- If I understood the code correctly, this solution appears to be none from CAP. It’s not consistent or partition tolerant because state server is started under the global name, and when split happens and some new live view mounts in the partition without state server, it will spawn a second server with the same name, which will result in two servers having different state. When split is resolved, one server will be just killed, since server does not implement any callbacks for state handover. It is also not available, because when cluster splits, the views which are in different partition then the state server, will just crash during the
GenServer.callto the state server. - When two views do the same action (consider the
messageslist from the README example), their order will be indefinite and it’s even worse, cause the action which will hit the state server first will be just overwritten by the second one. - Why add ACL to this solution?
- It seems that state server spawning is unbalanced, in a sense that the state server always spawns on the node where the first live view with this key mounts
But I like the idea and most of the interface, so I have these suggestions about how to improve the solution:
-
Decide on CAP. There are AP and CP solutions which I can suggest. First is AP, investigate Delta CRDT algorithms, Merkle Map versions, You can use library Horde (or is it Swarm) which utilizes this algorithm as a reference. If you want to have CP solution, I would suggest to not use the
globaland implement some persistent hashring to decide on the node where the state server spawns (no matter where the liveview was first mounted). -
I don’t see the use case for ACL, but even if there is one, it’s not that hard to implement it on top of the key-valye sync. Doing it inside the library just blurs the scope and, personally for me, looks odd.
-
Make most logs
debugor at least add some metadata so that users of the library could filter these messages out -
I believe that every distributed algorithm must have a good doc with implementation details and choice it makes in order for users to understand the possible drawbacks and failure scenarios.







