Skip to content

service

service

Shared helpers for the standalone serve() entry points.

The hub (terok_clearance.hub.server.serve) and the verdict helper (terok_clearance.verdict.server.serve) both expose serve() coroutines that drive the standalone CLI verbs (terok-clearance-hub serve / serve-verdict) used by integration tests. Both need the same two pieces of plumbing: log to stderr so the launching process picks it up, and block on SIGINT / SIGTERM until the operator tears them down.

The per-container supervisor in terok-sandbox composes ClearanceHub and VerdictServer directly — it owns its own lifecycle and signal handling, so it does not go through these helpers.

configure_logging(level=logging.INFO)

Route logs through the unified facility, always keeping stderr.

These serve() daemons are host processes whose stderr the launcher reads, so stderr=True keeps that pipe fed even on a journald host (where records also go to the journal). On a non-systemd host it falls back to that same stderr.

Source code in src/terok_clearance/runtime/service.py
def configure_logging(level: int = logging.INFO) -> None:
    """Route logs through the unified facility, always keeping stderr.

    These ``serve()`` daemons are host processes whose stderr the launcher
    reads, so ``stderr=True`` keeps that pipe fed even on a journald host
    (where records also go to the journal).  On a non-systemd host it falls
    back to that same stderr.
    """
    configure(identifier="terok-clearance-hub", level=level, stderr=True)

wait_for_shutdown_signal() async

Block the current task until SIGINT or SIGTERM arrives.

Source code in src/terok_clearance/runtime/service.py
async def wait_for_shutdown_signal() -> None:  # pragma: no cover — real signals
    """Block the current task until ``SIGINT`` or ``SIGTERM`` arrives."""
    stop = asyncio.Event()
    loop = asyncio.get_running_loop()
    for sig in (signal.SIGINT, signal.SIGTERM):
        loop.add_signal_handler(sig, stop.set)
    await stop.wait()