One line for every member of Solo, of the context its jobs get, of the jobs
it returns, of its queue and of its accumulators, with the section that
explains it. One line, too, for every parameter of the methods that make jobs.
What solo takes from the core is listed where it is explained. The rest of
ctx is in
The context at a glance
on the reference page of async_job, and value, done or cancel() of a
job are in Jobs and results on the jobs page.
Solo<S> is the base class of a controller. Its members fall into four groups
by who uses them: the whole process, a caller, the subclass, and an override in
the subclass.
| Member |
What it does |
Where |
Solo.observer |
One observer of every controller of the process, which watches and answers for nothing |
Watching every controller |
Solo.unansweredHandler |
A SoloUnansweredHandler that takes the errors nobody answered for, in place of the zone |
Answering for an error |
Solo.debug |
A callback that traces the queue, the state and the closing of every controller, while the life of each job goes to Job.debug |
Logs |
| Member |
What it does |
Where |
currentState |
The state for a reader outside a job, read without a checkpoint |
Observing state |
addListener(listener) |
Calls back synchronously inside every change of the state |
Observing state |
removeListener(listener) |
Removes the earliest registration equal to the listener |
Observing state |
isClosed |
Whether close() was called |
Three ways to stop |
isDraining |
Whether a close() that drains is still running the queue |
Three ways to stop |
isFinished |
Whether closing has finished and the state can no longer change |
externalSetState |
pending |
What is holding the controller right now, a running job included, or null |
What is holding the controller |
cancelAll() |
Clears the queue and cancels the running job; the controller stays open. force: true removes queued jobs made with cancellable: false too, and reason: names the reason every job it ends carries |
Three ways to stop |
close() |
Stops taking work and closes, cancelling what is queued and running or, with mode: SoloCloseMode.drain, running the queue first |
Three ways to stop |
A controller builds its own constructor and methods from these, and a caller
sees those. Every member here is protected.
| Member |
What it does |
Where |
Solo(initialState) |
The constructor a subclass calls as super(initialState), with the first state |
Quick start |
enqueue(body) |
Makes and queues the job a method of the controller usually returns |
Creating and scheduling jobs |
job(body) |
Makes a job without queueing it, for enqueueJob or for ctx.run as a child |
Creating and scheduling jobs |
enqueueJob(job) |
Queues a job made by job under a Policy, at the tail or, with first: true, at the head |
Queue and policies |
collect(handler) |
Makes an accumulator that hands one job the list of the events of its group |
One request per log line |
accumulate(handler, merge: ...) |
Makes an accumulator that merges the events of a group into one value |
Settings saved on every flip of a switch |
queue |
The jobs waiting to run, a SoloQueue |
Working the queue directly |
lastJobWhere(test) |
The last queued job that passes the test, else the running one if it passes and has not been cancelled, else null |
Working the queue directly |
current |
The running root job, or null when the controller is idle |
Working the queue directly |
hasListeners |
Whether any listener is registered |
Observing state |
externalSetState(state) |
Reflects a state an outside source has already changed |
externalSetState |
The engine calls these. The hooks do nothing by default, except the two that
hand an error on, and publish delivers the state: an override calls
super.publish first. Every member here is protected too. Dart does not carry
the annotation over to an override, so an override that should stay protected
repeats @protected.
| Member |
What it does |
Where |
onStart(job) |
A job body is about to run |
Watching every controller |
onFinish(job) |
A job has an outcome, a job dropped before its start included |
Watching every controller |
onError(job, error, stackTrace, answer: ...) |
Hears every error a job runs into and reports it, moving nothing |
Reporting an error |
onUnanswered(job, error, stackTrace) |
Answers for an error no outcome carries and a Failed nobody observes, by default through Solo.unansweredHandler or the zone |
Answering for an error |
onLog(job, message) |
A job called ctx.log |
Logs |
onChange(transition) |
The state changed, with a SoloTransition that says which job changed it |
Watching every controller |
onClose() |
The engine is about to finish closing, which is the place to release what the controller holds beside its jobs |
externalSetState |
onListenerError(error, stackTrace) |
A listener threw an error, which goes to the zone by default |
Observing state |
publish(previous, current) |
Calls the listeners and is the seam for a delivery of another kind |
A delivery of your own |
enqueue, job, collect and accumulate take the body first — for an
accumulator, a handler that also gets the events of its group — and these named
parameters after it. The first type argument of each is the working type, in
State and rules on the state page.
| Parameter |
Taken by |
What it does |
Where |
key |
enqueue, job, collect, accumulate |
The key of the job, what a Policy matches on and, without describe, what the job prints as: Job(key) |
Creating and scheduling jobs |
describe |
enqueue, job, collect, accumulate |
The label after the key for logs, observers and toString(): Job(key: label) |
Creating and scheduling jobs |
policy |
enqueue, collect, accumulate |
A Policy for enqueue, deciding what happens to a job whose key is already queued or running, or an AccumulationPolicy for an accumulator, deciding which waiting group an event joins |
Queue and policies, Choosing where events join |
timing |
collect, accumulate |
When a group may start, an AccumulationTiming: debounce or throttle |
Choosing when a group is ready |
merge |
accumulate |
A required, synchronous and pure function that merges an incoming event into the value of the group |
Start, cancellation and errors |
canStart |
enqueue, job, collect, accumulate |
Asked once as the job is about to start, ending it Cancelled(rules: canStart) on false |
The rules |
keepWhile |
enqueue, job, collect, accumulate |
Keeps the job while the state allows it, and on false cancels it Cancelled(rules: keepWhile) |
The rules |
cancellable |
enqueue, job, collect, accumulate |
false turns down manual cancellation and the parent’s, and closing once the job runs: a queued one close() drops |
A whole job |
timeout |
enqueue, job, collect, accumulate |
A deadline counted from the start of the body, after which the job ends Cancelled(timeout); with cancellable: false the call throws ArgumentError |
A deadline of a job |
ifFailed |
enqueue, job, collect, accumulate |
The state to write when the job fails, once the body, its children and cleanup are over |
The handlers |
isExpectedError |
enqueue, job, collect, accumulate |
Names the errors the job expects: one it names is heard by onError with never, and nobody is asked to answer for it |
Naming the expected errors |
ifCancelled |
enqueue, job, collect, accumulate |
The state to write when the job is cancelled, once the body, its children and cleanup are over |
The handlers |
What a body of solo gets as ctx: the core’s JobContext plus the state,
narrowed to the working type W of the job. join, abandonable, onDispose
and the rest of ctx are the core’s, in
The context at a glance
on the reference page of async_job. Here the checkpoints of the core,
check() and the waiting methods, also ask the rules of the job, as
ctx.state does, and so does ctx.each.
| Member |
What it does |
Where |
ctx.state |
The state as W, read at a checkpoint where a state the rules of the job refuse cancels the job |
Reading and updating state |
ctx.stateAs<T>() |
The state narrowed further to T, where a mismatch cancels the job |
Reading and updating state |
ctx.emit(next) |
The body’s only way to write the state, a synchronous one |
Reading and updating state |
ctx.child(body) |
Makes an unstarted child of this controller under the rules of this job, its working type W and keepWhile, for the code that holds only a context |
Children and chains |
ctx.run(child) |
Runs a child made by job(...) of this controller or by ctx.child and returns its value; a job of the core or of another controller is refused with an ArgumentError |
Children and chains |
ctx.start(child) |
Starts such a child right now and leaves its outcome to whoever holds it |
Children and chains |
ctx.runAll(children) |
Runs such children side by side and stops the rest as soon as one of them goes wrong |
Children and chains |
ctx.each(stream, onData) |
Starts a child that hands the events of a stream to onData one at a time, with the child’s SoloContext, at a checkpoint where a state the rules of the job refuse cancels the job instead |
Processing a stream |
What enqueue, job, enqueueJob and an accumulator’s add return, and what
queue.jobs, current and lastJobWhere hand out: a Job<T> of the core
plus the queue. value, done, outcome, cancel() and ignoreFailure()
are the core’s, in the table of Jobs and results on
the jobs page. A method the screen calls declares Job<T>, and SoloJob<T>
only for a caller that reads isQueued. A method that makes a child for
ctx.run declares SoloJob<T>: ctx.run takes a ChildJob<T>, which
SoloJob<T> is and Job<T> is not.
The type of queue. Removal touches waiting jobs only: the running job is not
the queue’s. A job made with cancellable: false stays unless the call says
force: true, and a removed job ends Cancelled(manual) or with the reason:
the call passes.
The type collect and accumulate return. Keep one instance in a late final
field: events combine only within one accumulator, even under the same key.
| Member |
What it does |
Where |
accumulator.add(event) |
Adds the event to a waiting group or starts one, and returns the group’s job, which every caller continues through shared() |
Start, cancellation and errors |
| Type |
What it is |
Where |
Policy |
What enqueueJob and enqueue do with a job whose key is already queued or running: sequential, droppable, keepLatest or restart |
Queue and policies |
SoloCloseMode |
How close() stops: cancel or drain |
Three ways to stop |
SoloUnansweredHandler |
The type of Solo.unansweredHandler: a function of the controller, the job, the error and its stack trace |
Answering for an error |
SoloObserver |
What Solo.observer takes, one or several joined by SoloObserver.all: onStart, onFinish, onError, onLog, onChange and onClose of every controller, plus onCreate |
Watching every controller |
SoloTransition |
One change of the state: the states before and after, the job that made it and a revision that grows by one per change |
Watching every controller |
SoloPending |
What pending returns: a SoloPendingJob with its job and phase, a SoloPendingQueue with its jobs, or a SoloPendingStream |
What is holding the controller |
SoloPhase |
Where the job of a SoloPendingJob stands: body, children or cleanup |
What is holding the controller |
SoloStream |
A mixin that adds a broadcast stream of the states |
Observing state |
AccumulationPolicy |
Which waiting group an event joins: join, adjacent or replace |
Choosing where events join |
AccumulationTiming |
When a group may start: debounce or throttle |
Choosing when a group is ready |
SoloCancelReason |
The base of the reasons solo adds to the core’s: RulesCancelReason, ClosedCancelReason, DuplicateCancelReason and ReplacedCancelReason |
Cancellation details |