Pure scheduler state machine.
The scheduler never starts processes or sends messages. The shell feeds it events and then asks three questions, in this order, after every event:
next-assignments which [worker-id ns] pairs to send nowdrain-spawns which new worker ids to startdrain-shutdowns which worker ids to tell to shut downWorker ids come from the scheduler (:first-id, then up by one) and are
never reused, so a replacement worker is always a new id. Watch mode
starts each run's ids after the last run's, so a late event from an
earlier run can never be taken for one of this run's workers.
Events it understands (all others are ignored):
{:event :worker/ready :worker id}{:event :ns/end :worker id :ns sym} (the worker always sends this last,
also after :ns/error){:event :ns/error ...}, {:event :assertion :type :fail|:error ...},
{:event :var/end :fail n :error n ...} and an :output with a
:protocol-error mark the run as failed{:event :worker/exit :worker id :code n} emitted by the poolWorker statuses: :starting, :idle, :busy, :retiring (shutdown
requested, process not yet gone). A worker that has exited is removed.
Pure scheduler state machine.
The scheduler never starts processes or sends messages. The shell feeds it
events and then asks three questions, in this order, after every event:
* `next-assignments` which `[worker-id ns]` pairs to send now
* `drain-spawns` which new worker ids to start
* `drain-shutdowns` which worker ids to tell to shut down
Worker ids come from the scheduler (`:first-id`, then up by one) and are
never reused, so a replacement worker is always a new id. Watch mode
starts each run's ids after the last run's, so a late event from an
earlier run can never be taken for one of this run's workers.
Events it understands (all others are ignored):
* `{:event :worker/ready :worker id}`
* `{:event :ns/end :worker id :ns sym}` (the worker always sends this last,
also after `:ns/error`)
* `{:event :ns/error ...}`, `{:event :assertion :type :fail|:error ...}`,
`{:event :var/end :fail n :error n ...}` and an `:output` with a
`:protocol-error` mark the run as failed
* `{:event :worker/exit :worker id :code n}` emitted by the pool
Worker statuses: `:starting`, `:idle`, `:busy`, `:retiring` (shutdown
requested, process not yet gone). A worker that has exited is removed.(crash-events {:keys [assignments]} {:keys [event worker code at reason]})Events to show for event when it is a :worker/exit of a worker that
held an assignment: an :ns/error describing the crash, then the :ns/end
the dead worker could not send. Empty for any other event. Call before
handle-event. A :reason on the exit event (the parent killed the
worker, say) is added to the message.
Events to show for `event` when it is a `:worker/exit` of a worker that held an assignment: an `:ns/error` describing the crash, then the `:ns/end` the dead worker could not send. Empty for any other event. Call before `handle-event`. A `:reason` on the exit event (the parent killed the worker, say) is added to the message.
(done? {:keys [queue serial workers] :as state})True when nothing is in flight and nothing more will be assigned: the queues are empty, fail-fast stopped the run, or no worker can be started.
True when nothing is in flight and nothing more will be assigned: the queues are empty, fail-fast stopped the run, or no worker can be started.
(drain-shutdowns state)[state' [worker-id ...]]: workers to tell to shut down, namely those
retired by isolate mode plus idle workers beyond what the remaining work
needs (highest ids first). Retiring workers stay known until their exit.
`[state' [worker-id ...]]`: workers to tell to shut down, namely those retired by isolate mode plus idle workers beyond what the remaining work needs (highest ids first). Retiring workers stay known until their exit.
(drain-spawns state)[state' [worker-id ...]]: new workers to start so that enough non-busy
workers exist for the remaining work, never exceeding :workers alive
and busy together. Each id is fresh.
`[state' [worker-id ...]]`: new workers to start so that enough non-busy workers exist for the remaining work, never exceeding `:workers` alive and busy together. Each id is fresh.
(handle-event state {:keys [event worker ns] :as ev})Fold one event into the state. Total: unknown events and events from unknown workers are ignored.
Fold one event into the state. Total: unknown events and events from unknown workers are ignored.
(holding state worker)The namespace worker is running, or nil.
The namespace `worker` is running, or nil.
(init {:keys [parallel serial]}
{:keys [workers fail-fast? isolate? durations first-id]})State for plan {:parallel [ns ...] :serial [ns ...]}.
opts:
:workers maximum concurrent workers (default 1):fail-fast? stop assigning after the first failure:isolate? each worker runs one namespace, then is retired:durations {ns millis} from earlier runs, for longest-first order:first-id the first worker id to hand out (default 1)State for `plan` `{:parallel [ns ...] :serial [ns ...]}`.
opts:
* `:workers` maximum concurrent workers (default 1)
* `:fail-fast?` stop assigning after the first failure
* `:isolate?` each worker runs one namespace, then is retired
* `:durations` `{ns millis}` from earlier runs, for longest-first order
* `:first-id` the first worker id to hand out (default 1)(interrupt state keep)[state' [[worker-id ns] ...]]: give up the namespaces that busy workers
other than keep (the worker whose failure stopped the run, or nil) hold.
Their workers become :retiring, to be killed; their exit is then not a
crash, since they no longer hold anything. Used by fail-fast.
`[state' [[worker-id ns] ...]]`: give up the namespaces that busy workers other than `keep` (the worker whose failure stopped the run, or nil) hold. Their workers become `:retiring`, to be killed; their exit is then not a crash, since they no longer hold anything. Used by fail-fast.
(live-workers state)Ids of workers that have not exited, in any status.
Ids of workers that have not exited, in any status.
(next-assignments state)[state' [[worker-id ns] ...]]: work to send now. Assigns to idle workers
in id order; the serial batch only once the parallel batch is finished and
every worker is idle, and then one namespace at a time.
`[state' [[worker-id ns] ...]]`: work to send now. Assigns to idle workers in id order; the serial batch only once the parallel batch is finished and every worker is idle, and then one namespace at a time.
(next-id state)The id the next spawned worker will get.
The id the next spawned worker will get.
(pending {:keys [queue serial]})Namespaces not yet assigned, parallel batch first.
Namespaces not yet assigned, parallel batch first.
(set-max-workers state n)Allow up to n (at least 1) concurrent workers from now on. Workers
already alive beyond a lower limit are not stopped; idle ones are
trimmed by drain-shutdowns as the work runs out.
Allow up to `n` (at least 1) concurrent workers from now on. Workers already alive beyond a lower limit are not stopped; idle ones are trimmed by `drain-shutdowns` as the work runs out.
(stopped? {:keys [fail-fast? failed?]})True when fail-fast is on and a failure has happened: nothing new is assigned.
True when fail-fast is on and a failure has happened: nothing new is assigned.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |