MCPcopy
hub / github.com/benoitc/gunicorn / DirtyArbiter

Class DirtyArbiter

gunicorn/dirty/arbiter.py:49–1152  ·  view source on GitHub ↗

Dirty arbiter that manages the dirty worker pool. The arbiter runs an asyncio event loop and handles: - Spawning and managing dirty worker processes - Accepting connections from HTTP workers - Routing requests to available dirty workers - Monitoring worker health via heartb

Source from the content-addressed store, hash-verified

47
48
49class DirtyArbiter:
50 """
51 Dirty arbiter that manages the dirty worker pool.
52
53 The arbiter runs an asyncio event loop and handles:
54 - Spawning and managing dirty worker processes
55 - Accepting connections from HTTP workers
56 - Routing requests to available dirty workers
57 - Monitoring worker health via heartbeat
58 """
59
60 SIGNALS = [getattr(signal, "SIG%s" % x) for x in
61 "HUP QUIT INT TERM TTIN TTOU USR1 USR2 CHLD".split()]
62
63 # Worker boot error code
64 WORKER_BOOT_ERROR = 3
65
66 def __init__(self, cfg, log, socket_path=None, pidfile=None):
67 """
68 Initialize the dirty arbiter.
69
70 Args:
71 cfg: Gunicorn config
72 log: Logger
73 socket_path: Path to the arbiter's Unix socket
74 pidfile: Well-known PID file location for orphan detection
75 """
76 self.cfg = cfg
77 self.log = log
78 self.pid = None
79 self.ppid = os.getpid()
80 self.pidfile = pidfile # Well-known location for orphan detection
81
82 # Use a temp directory for sockets
83 self.tmpdir = tempfile.mkdtemp(prefix="gunicorn-dirty-")
84 self.socket_path = socket_path or os.path.join(
85 self.tmpdir, "arbiter.sock"
86 )
87
88 self.workers = {} # pid -> DirtyWorker
89 self.worker_sockets = {} # pid -> socket_path
90 self.worker_connections = {} # pid -> (reader, writer)
91 self.worker_queues = {} # pid -> asyncio.Queue
92 self.worker_consumers = {} # pid -> asyncio.Task
93 self._worker_rr_index = 0 # Round-robin index for worker selection
94 self.worker_age = 0
95 self.alive = True
96 self.num_workers = self.cfg.dirty_workers # Dynamic count for TTIN/TTOU
97
98 self._server = None
99 self._loop = None
100 self._pending_requests = {} # request_id -> Future
101
102 # Per-app worker allocation tracking
103 # Maps import_path -> {import_path, worker_count, original_spec}
104 self.app_specs = {}
105 # Maps import_path -> set of worker PIDs that have loaded the app
106 self.app_worker_map = {}

Calls

no outgoing calls