fireproofsocks
The use for keys: :duplicate in Registries?
I find it surprising that :via is not supported for duplicate registries. If you can’t register a pool of processes under the same name what exactly is the use-case for having duplicate-key registries? The docs include an example of dispatching (Registry — Elixir v1.21.0-dev), but I’m not clear how you would even put a process into a custom Registry if :via is not allowed. What am I missing? How do you actually use a custom Registry with duplicate keys?
Most Liked
al2o3cr
:via isn’t specifically related to Registry, it’s just a fancy way to tell :gen’s name handling to call register_name and whereis_name on a specified module:
(related: Elixir’s wrappers transform a bare atom name into {:local, name})
Conversely, Registry isn’t otherwise related to process naming - it’s just a key-value store that automatically cleans up keys when the registering process exits.
The simplest thing to build with a :duplicate registry is a local publish-subscribe bus:
- processes that are interested in a topic
{:foo, 123}useRegistry.registerto “subscribe” to that key - when a message needs to be delivered for topic
{:foo, 123}, the sender usesRegistry.dispatchto send it to each PID - when a process that’s subscribed to a topic stops, its registration is automatically cleaned up
You might even use both a :unique and a :duplicate registry with the same keys, for instance in the classic “multiplayer game” architecture:
- the
:uniqueregistry tracks a GenServer per “game”. A:viatuple pointing to this registry is used when sending moves, joins, etc to the game - the
:duplicateregistry tracks the Liveview processes of players per “game”, and is used to distribute updates to all players
fireproofsocks
Thank you for the informative responses! This is stuff that I’m going to have to ponder about for a while, but I see the set/get is pretty straightforward using Registry.register/3 and Registry.lookup/2:
iex> {:ok, _} = Registry.start_link(keys: :duplicate, name: ClusterRegistry)
iex> Registry.register(ClusterRegistry, :group, "a")
iex> Registry.register(ClusterRegistry, :group, "b")
iex> Registry.register(ClusterRegistry, :group, "c")
iex> Registry.lookup(ClusterRegistry, :group)
[{#PID<0.148.0>, "a"}, {#PID<0.148.0>, "b"}, {#PID<0.148.0>, "c"}]
What is interesting to me is that Registry.register/3 really is all about storing the current process – the value seems almost secondary. The other thing that is interesting is that when a process terminates, anything that it registered gets removed (as. you pointed out Matt):
iex> Task.start(fn ->
Registry.register(ClusterRegistry, :group, "hello?")
Process.sleep(10_000)
end)
iex> Registry.lookup(ClusterRegistry, :group)
[{#PID<0.148.0>, "a"}, {#PID<0.148.0>, "b"}, {#PID<0.148.0>, "c"}, {#PID<0.148.0>, "hello?"}]
# Wait 10 seconds
iex> Registry.lookup(ClusterRegistry, :group)
[{#PID<0.148.0>, "a"}, {#PID<0.148.0>, "b"}, {#PID<0.148.0>, "c"}]
I feel like I’m only becoming dimly aware of the things that you can do with these tools…
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








