Skip to content

blackbull.server.multiworker

blackbull.server.multiworker

Multi-worker master process for BlackBull.

Uses a pre-fork model
  1. The master binds sockets once (via ASGIServer.open_socket).
  2. N worker processes are forked; each inherits the socket file descriptors.
  3. The master monitors workers in a synchronous loop and respawns any that crash.
  4. On SIGTERM or SIGINT the master sends SIGTERM to all workers, waits up to shutdown_timeout seconds, then SIGKILLs any that are still alive.

When reload=True the master additionally runs a file watcher; on any matching change it SIGTERMs the workers, marks the listening sockets inheritable, and os.execvp\ s itself with the original argv — the fresh process adopts the inherited fds and re-forks workers from the new code. See :mod:blackbull.server.reload.

The worker entry point is :func:blackbull.server.worker.run_worker. Each worker runs its own asyncio event loop and its own ASGI lifespan cycle.

Usage::

from blackbull.server.multiworker import MultiWorkerServer

server = MultiWorkerServer(app, raw_sockets, ssl_context, workers=4)
server.run()          # blocks until SIGTERM / SIGINT

MultiWorkerServer

Spawns and supervises N worker processes.

Parameters

app: ASGI application callable. raw_sockets: Pre-bound sockets that every worker will inherit. ssl_context: TLS context, or None for plain HTTP. workers: Number of worker processes to maintain. max_connections: Per-worker connection limit forwarded to :class:ASGIServer. shutdown_timeout: Seconds to wait for graceful shutdown before sending SIGKILL.

run()

Spawn workers and block until a shutdown signal is received.

When reload is enabled the master also runs a file watcher and re-execs itself on any matching change — see :mod:blackbull.server.reload.