Packages
snakepit
0.1.1
0.13.0
0.12.0
0.11.1
0.11.0
0.10.1
0.10.0
0.9.1
0.9.0
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.11
0.6.10
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.1
0.5.0
0.4.3
0.4.2
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.2
0.1.1
0.1.0
High-performance pooler and session manager for external language integrations. Supports Python, Node.js, Ruby, and more with gRPC streaming, session management, and production-ready process cleanup.
Current section
Files
Jump to
Current section
Files
lib/snakepit/pool/worker_starter.ex
defmodule Snakepit.Pool.Worker.Starter do
@moduledoc """
Supervisor wrapper for individual workers that provides automatic restart capability.
This module implements the "Permanent Wrapper" pattern that allows DynamicSupervisor
to automatically restart workers when they crash, while keeping the actual worker
process as :transient (so it doesn't restart during coordinated shutdown).
## Architecture
```
DynamicSupervisor (WorkerSupervisor)
└── Worker.Starter (permanent, one per worker)
└── Worker (transient, actual worker process)
```
When a Worker crashes:
1. Worker.Starter detects the crash via its :one_for_one strategy
2. Worker.Starter automatically restarts the Worker (because Worker is :permanent in this context)
3. Pool is notified via :DOWN message but doesn't need to manage restarts
4. New Worker re-registers itself automatically
This decouples the Pool from worker replacement logic.
"""
use Supervisor
require Logger
@doc """
Starts a worker starter supervisor.
## Parameters
* `worker_id` - Unique identifier for the worker
"""
def start_link(worker_id) when is_binary(worker_id) do
Supervisor.start_link(__MODULE__, worker_id, name: via_name(worker_id))
end
@doc """
Returns a via tuple for this starter supervisor.
"""
def via_name(worker_id) do
Snakepit.Pool.Worker.StarterRegistry.via_tuple(worker_id)
end
@impl true
def init(worker_id) do
# Check if the Pool is already terminating
case Process.whereis(Snakepit.Pool) do
nil ->
# Pool is dead, don't start workers
Logger.debug("Aborting worker starter for #{worker_id} - Pool is dead")
:ignore
_pid ->
Logger.debug("Starting worker starter for #{worker_id}")
children = [
%{
id: worker_id,
start: {Snakepit.Pool.Worker, :start_link, [[id: worker_id]]},
# Within this supervisor, the worker restarts on crashes but not during shutdown
restart: :transient,
type: :worker
}
]
Supervisor.init(children, strategy: :one_for_one)
end
end
end