shahryarjb
How to restart a genserver under DynamicSupervisor which is started under PartitionSupervisor
Hello friends, I think I am creating a bad config for my project.
I have a genserver is started under DynamicSupervisor and I start it with PartitionSupervisor
my Application config:
def start(_type, _args) do
children = [
{Registry, keys: :unique, name: MishkaJobWorkerRegistry},
{PartitionSupervisor, child_spec: DynamicSupervisor, name: MishkaJobWorkerSupervisor},
]
opts = [strategy: :one_for_one, name: MishkaInstaller.Supervisor]
Supervisor.start_link(children, opts)
end
It is my Genserver simple code:
defmodule Queue.Job do
use GenServer
require Logger
def start_link(args) do
id = Map.get(args, :worker)
type = Map.get(args, :type, :normal)
GenServer.start_link(__MODULE__, [], name: via(id, type))
end
@impl true
def init(state \\ %{}) do
{:ok, state}
end
@doc false
def child_spec(process_name) do
%{
id: __MODULE__,
start: {__MODULE__, :start_link, [process_name]},
restart: :transient,
max_restarts: 4
}
end
defp via(id, value) do
{:via, Registry, {MishkaJobWorkerRegistry, id, value}}
end
end
and I start like this:
def start_job_worker(args) do
DynamicSupervisor.start_child(
{:via, PartitionSupervisor, {MishkaJobWorkerSupervisor, self()}},
{Queue.Job, args}
)
end
But if my genserver crashes unexpectedly, it does not reset it and when I check the process of my genserver , it returns false.
Another problem is
when I use this to terminate one of genserver by pid, it returns not found
DynamicSupervisor.terminate_child(MishkaJobWorkerSupervisor, pid)
Where I am creating a bug?
Thank you in advance
Marked As Solved
alisinabh
when I use this to terminate one of genserver by
pid, it returns not found
DynamicSupervisor.terminate_child(MishkaJobWorkerSupervisor, pid)
Where I am creating a bug?
The problem is that you are referencing the wrong name here. MishkaJobWorkerSupervisor is not the name that you should use. If you pay close attention to how the process is started here you can see that the :via tuple has been used. To terminate the child, you need to use the same via tuple.
def start_job_worker(args) do
DynamicSupervisor.start_child(
{:via, PartitionSupervisor, {MishkaJobWorkerSupervisor, self()}},
{Queue.Job, args}
)
end
So to terminate you can do something like
DynamicSupervisor.terminate_child(
{:via, PartitionSupervisor, {MishkaJobWorkerSupervisor, self()}},
# Remember that because you used self() for the partition key, you need to call this from the same process or replace self() with the correct pid.
pid
)
Also Liked
al2o3cr
This line is the problem - MishkaJobWorkerSupervisor is the PartitionSupervisor, so the PID isn’t found because it’s a child of one of the supervisor’s children.
The call doesn’t crash because DynamicSupervisor.terminate_child sends a {:terminate_child, pid} message, which is handled by the machinery for :supervisor.terminate_child.
To accurately target the message, you need to use a :via tuple pointing to the PartitionSupervisor:
{:via, PartitionSupervisor, {MishkaJobWorkerSupervisor, self()}}
HOWEVER
If the process that’s calling terminate_child isn’t the same one that started the child, I’m not sure that’s going to find the correct DynamicSupervisor. ![]()
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









