stevensonmt
Registry.update_value/3 error when called from Task but not from iex
I am trying to grow my skills a bit and exploring the Registry module. I have a custom registry set up as follows:
defmodule MyReg do
def start_link() do
Registry.start_link(keys: :unique, name: MyReg)
Registry.register(MyReg, :default_key, MapSet.new())
end
I want to iterate over a collection and store each item in the MapSet accessed by the :default_key but also use each item as another key with it’s own value.
# in the same module
def register(item, value) do
case Registry.register(MyReg, item, [value]) do
{:ok, _} ->
# the item was not previously registered so add it to the collection of keys
Registry.update_value(MyReg, :default_key, fn keys -> MapSet.put(keys, item) end)
_ ->
# if the item has already been registered, update it's values
Registry.update_value(MyReg, item, fn vals -> [value | vals] end)
end
end
When I run this manually from within iex -S mix it seems to work great. But when I try to run it as follows it fails at the update_value step.
MyReg.start_link()
collection
|> Task.async_stream(fn {item, value} ->
MyReg.register(item, value)
end)
|> Enum.to_list()
# [ok: :error, ok: :error, ...]
> Registry.lookup(MyReg, :default_key)
# MapSet.new()
I believe that the problem is that somehow the processes spawned by Task.async_stream do not have access to the registry created with MyReg.start_link, but I don’t know why.
After enumerating over the collection I can look at the contents of the registry and see that the initial start_link call was successful but that it was never modified after that.
Marked As Solved
mudasobwa
As per documentation, this function updates the value for key for the current process in the unique registry.
Your example might be simplified to:
iex|💧|1 ▸ Registry.start_link(keys: :unique, name: MyReg)
iex|💧|2 ▸ Registry.register(MyReg, :default_key, :value)
iex|💧|3 ▸ spawn fn -> Registry.update_value(MyReg, :default_key, fn _ ->
...|💧|3 ▸ :new_value
...|💧|3 ▸ end) |> IO.inspect() end
:error
Registry.lookup/2 also returns a list of tuples {pid(), value}. You might turn your MyReg into GenServer and use its handle_cast/2/handle_call/2 to amend/query the backed registry.
Also Liked
al2o3cr
Cross-linking a useful analogy from another thread:
stevensonmt
Thanks, dropping back to ETS for this use case is probably the way to go.
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








