riccardomanfrin
Hi buddies,
in my project I was using Supervisor to start and terminate+delete children dynamically. Elixir complained I should be using a DynamicSupervisor:
warning: Supervisor.terminate_child/2 with a PID is deprecated, please use DynamicSupervisor instead
(elixir 1.16.1) lib/supervisor.ex:1030: Supervisor.terminate_child/2
So I switched to that. Unfortunately the doc for DynamicSupervisor points out that the id of the child_spec, while required, is ignored:
Note that while the
:idfield is still required in the spec, the value is ignored and therefore does not need to be unique.
The effect of this is the following: with Supervisor.which_children I was able to see the child spec id of the child along with its pid:
iex(53)> Supervisor.which_children(MySup)
[
{"foo_child-0012041214", #PID<0.509.0>, :worker, [ChildModule]}
]
Instead, with DynamicSupervisor, which_children api returns :undefined as the first element of the tuple:
iex(31)> DynamicSupervisor.which_children(MySup)
[{:undefined, #PID<0.270.0>, :worker, [ChildModule]}]
The problem is that I need to command the termination of children via external APIs, which don’t of course have notion of pids
.
With Supervisor I could directly read the child spec id. Do I now have to explicitly instrument the Registry boilerplate? is there some idiomatic shortcut to obtain a similar result?
Thanks
Trending in Questions
Other Trending 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
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #ai
- #phoenix_html
- #elixirconf-us
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 6- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
DidactMacros
Bit rusty on this as I have been on phoenix, by dynamic supervisors have a changing pool of workers, so having names for them might be a bit tricky without some sort of registry that can be used to identify the child by composite ID (usually the child module plus name an identifying index).
Should you require more clarity I can quickly refer back to appropriate material.
dimitarvp
I am not sure what’s the problem here? I have written a worker + a
DynamicSupervisorimplementation that successfully commands children to stop, by user-given name.The trick was to use a
Registryfor name registration. Oh, and you can’t rely onProcess.whereisandDynamicSupervisor.which_childrenfor exact lookups, you have to useGenServer.whereis.Here’s what I have in files lying around, and I just tested it. Obviously change
YYYto your app namespace.The worker:
The dynamic supervisor:
Also make sure to add those children to your
Application.startreturn value (i.e. the children of your app):YYY.OneDynamicSupervisor{Registry, [keys: :unique, name: :one_registry]}You can see that I have included a function to stop a child (
YYY.OneWorker.stop/1). It uses a:viatuple to locate and stop it. I have not included a function to locate a child’s PID but it’s as simple as this:That should solve your problem.
Caveats and remarks:
YYY.namespace should be changed to your app’s;OneWorkerandOneDynamicSupervisornames are placeholders, IMO change them before doing a GIT commit in your repo;:one_registryname of the registry should be changed;IO.putscalls, I’ve put them just for demonstration;request_idis simply your user-supplied ID / name, feel free to change it to anything else (and it can be anything else besides an integer as well).riccardomanfrin
Thank you, @dimitarvp .
I think my implementation was originally similar to yours. The problem I had with that (and possibly the reason why I posted the question), is that invoking
YYY.OneWorker.stop, would in facts stop the worker, but than this would be restarted right after..So I came to the conclusion that I should have passed through the DynamicSupervisor
terminate_childAPI to stop the genserver. This seemed to work, provided that I had a way to find the “pid” to give as argument to theterminate_child.Your approach is to instead directly stop the child process and use the option
I hadn’t found this option in the DynamicSupervisor doc so I completely missed it. Using this option solves the restart problem.
At this point I can also avoid the usage of Registry at all and just use the
{:global, term()}to later on stop the process.Do you know why the
:transientoption has to be provided in eitheruse Genserverdeclaration and in the child spec?D4no0
Transient is a restart strategy that restarts the process only when the process crashes abnormally:
:transient- the child process is restarted only if it terminates abnormally, i.e., with an exit reason other than:normal,:shutdown, or{:shutdown, term}.dimitarvp
Because I am paranoid. Technically it should work if it’s only in either place. But don’t quote me on that, I say just try it.
mudasobwa
The default for the
GenServeris defined inuse. The supervisor might override it.