Packages
snakepit
0.5.0
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/application.ex
defmodule Snakepit.Application do
@moduledoc """
Application supervisor for Snakepit pooler.
Starts the core infrastructure:
- Registry for worker process registration
- StarterRegistry for worker starter supervisors
- ProcessRegistry for external PID tracking
- SessionStore for session management
- WorkerSupervisor for managing worker processes
- Pool manager for request distribution
"""
use Application
require Logger
@impl true
def start(_type, _args) do
# Check if pooling is enabled (default: false to prevent auto-start issues)
pooling_enabled = Application.get_env(:snakepit, :pooling_enabled, false)
IO.inspect(
pooling_enabled: pooling_enabled,
env: Mix.env(),
label: "Snakepit.Application.start/2"
)
# Get gRPC config for the Elixir server
grpc_port = Application.get_env(:snakepit, :grpc_port, 50051)
# Always start SessionStore as it's needed for tests and bridge functionality
base_children = [
Snakepit.Bridge.SessionStore,
Snakepit.Bridge.ToolRegistry
]
pool_children =
if pooling_enabled do
pool_config = Application.get_env(:snakepit, :pool_config, %{})
pool_size = Map.get(pool_config, :pool_size, System.schedulers_online() * 2)
Logger.info("🚀 Starting Snakepit with pooling enabled (size: #{pool_size})")
[
# Start the central gRPC server that manages state
{GRPC.Server.Supervisor,
endpoint: Snakepit.GRPC.Endpoint, port: grpc_port, start_server: true}
|> tap(fn spec ->
IO.inspect(spec, label: "Adding GRPC.Server.Supervisor to children")
end),
# Task supervisor for async pool operations
{Task.Supervisor, name: Snakepit.TaskSupervisor},
# Registry for worker process registration
Snakepit.Pool.Registry,
# Registry for worker starter supervisors
Snakepit.Pool.Worker.StarterRegistry,
# Process registry for PID tracking
Snakepit.Pool.ProcessRegistry,
# Worker supervisor for managing worker processes
Snakepit.Pool.WorkerSupervisor,
# Main pool manager
{Snakepit.Pool, [size: pool_size]},
# Application cleanup for hard process termination guarantees
# MUST BE LAST - terminates FIRST to ensure workers have shut down
Snakepit.Pool.ApplicationCleanup
]
else
Logger.info("🔧 Starting Snakepit with pooling disabled")
[]
end
children = base_children ++ pool_children
opts = [strategy: :one_for_one, name: Snakepit.Supervisor]
result = Supervisor.start_link(children, opts)
IO.inspect(System.monotonic_time(:millisecond), label: "Snakepit.Application started at")
result
end
@impl true
def stop(_state) do
IO.inspect(System.monotonic_time(:millisecond),
label: "Snakepit.Application.stop/1 called at"
)
:ok
end
end