Operations¶
Running the system¶
# coordinator (single process — the design mandates one server)
n4cluster server --host 0.0.0.0 --port 8765 --state ./cluster-state --log-file server.log
# workers (inside a provisioned nirs4all environment), repeated per machine
n4cluster worker --server http://HOST:8765 --labels site=lab --slots 2
When authentication is enabled, set N4CLUSTER_TOKEN through your shell or secret
manager before starting the coordinator and workers; the CLI reads it
automatically.
Watch live state at http://HOST:8765/ui (Web dashboard) or with n4cluster jobs /
n4cluster workers / n4cluster logs.
Recovery model¶
Leasing is the backbone of correctness:
A lease has a TTL; every heartbeat renews the active leases, so a task that runs longer than the TTL is not reaped while its worker is healthy.
If a worker goes silent past
worker_dead_after_s, it is marked dead; the reaper requeues its in-flight tasks (or fails them once attempts are exhausted).A cancelled job’s reaped lease is moved to
cancelled, never relaunched.idempotency_keydeduplicates submissions (a unique index + race handling).
Task state machine¶
stateDiagram-v2
[*] --> queued
queued --> leased
queued --> cancelled
leased --> running
leased --> queued: lease expired / retry
leased --> cancelled
running --> succeeded
running --> failed
running --> queued: lease expired / retry
running --> cancelled
failed --> queued: retry
succeeded --> [*]
failed --> [*]
cancelled --> [*]
State changes always go through the scheduler’s transitions, which the database enforces —
there is no UPDATE … status around them.
Routing¶
The scheduler matches a task’s requirements against each worker: labels, a soft memory
floor, a fail-closed min_gpu_count, and PEP 440 packages specifiers checked against the
versions the worker declared. An nirs4all.run job implicitly requires nirs4all present,
so it never routes to a worker that can’t prove the library.
Logging & observability¶
Server and worker emit structured logs (--log-level, --log-file): lifecycle, reaper
errors, dead workers, job finalization, version divergence, and per-task progress. Every
event is also persisted and fanned out over the WebSocket streams.