Sagents.LocalRegistry (Sagents v0.12.0)
Copy MarkdownStarts Elixir's Registry for the :local backend, tolerating a restart that
races the previous registry's own shutdown.
Why this exists
Registry.start_link/1 starts a Registry.Supervisor registered under the
given name, and that supervisor's children are Registry.Partition processes
registered under derived names such as Sagents.Registry.PIDPartition0.
Registry.Partition traps exits, because it links to every registered
process. So when Sagents.Registry dies abnormally, the partition does not
die with it: it receives the exit signal as a message and terminates
asynchronously, holding its registered name for a few milliseconds longer.
Sagents.Supervisor restarts its failed child immediately, well inside that
window. Registry.Supervisor.init/1 then tries to start a partition under a
name the outgoing one still holds and gets {:already_started, pid}. The
restart fails, and because a failed restart is not something a supervisor
retries its way out of, Sagents.Supervisor gives up and exits :shutdown —
taking the registry, both dynamic supervisors and every running agent with it,
permanently. Nothing below it comes back until the host application's own
supervisor restarts the whole subtree.
This module closes that window: on an :already_started collision it waits
for the straggler to actually exit, then retries. The wait is a monitor, not a
sleep, so it costs exactly as long as the collision lasts.
Only the :local backend needs this. Under :horde the name
Sagents.Registry belongs to Horde.RegistryImpl, which Horde's own
supervisor restarts internally, so there is no name for a restart to collide
with.
This covers the case where Registry.Supervisor itself dies. The other
:local failure mode, where the supervisor survives and its partition is
replaced with empty tables, produces no failed child at all and is handled by
Sagents.RegistryWatcher.
Summary
Functions
@spec start_link(keyword()) :: Supervisor.on_start()
Start Registry with opts, retrying past a name still held by the previous
registry's terminating partition.
Every retry is gated on observing the straggler actually exit, so the retry count bounds how many distinct collisions are tolerated rather than how long this blocks. If a straggler does not exit within 1000ms, the underlying error is returned instead of retrying against it.