api_command_queue
Pure Dart command queue primitives for retryable API work, terminal failures, and offline-first orchestration.
0.4.0
166 downloads/mo
#1507 most downloaded on pub.dev
tribus-digital/api_command_queue
What this package is like to depend on
Last release 10 days ago
14 Aug 2026
Release timing varies
gaps range from 2 weeks to 3 months
Nearly every release is documented
notes for 4 of 4 stable releases
Nothing withdrawn
no release was ever pulled
4 months old
4 releases · first in 2026
4 releases in the last 12 months
see the full history below
Release timeline
4 releases · Apr 2026 to Aug 2026Releases
latest 4-
0.4.014 Aug 2026Release notes
Open source →-
Added
ApiCommandOrchestrator.autoFlushWhenDue, off by default.0.3.0 stopped
flush()sleeping a failed command's backoff, which means a retry now waits for something to trigger the next flush. A consumer driving flushes from connectivity changes and user activity will not retry at all on a device sitting idle - the ladder simply stops.With this on, the orchestrator keeps a single timer set to the earliest
nextDueAtacross its queues and flushes when it fires, so retries progress on their own again. The timer is cancelled while processing is disabled and on close, and has a one second floor so a due command a flush cannot clear becomes a slow poll rather than a spin.Consumers that already drive flushing on their own schedule do not need it.
-
nextDueAtno longer counts a command that is currently being sent. It is not waiting for a flush, and reporting it as due made a caller scheduling against it fire repeatedly for as long as the request took. -
flushAlljoins a flush already in progress rather than starting a second walk beside it, and asks the running one to make another pass before it finishes so work queued behind the point it had reached is still sent. Previously two callers - a startup flush and a sync, say - walked every queue independently. -
A joined flush only makes a second pass if something is actually due behind the one that just finished, rather than re-walking every queue to find out.
-
A lull between commands no longer reports the queues as idle while a flush is still walking them.
-
The aggregate flush status is only emitted when it actually changes. Queues emit on every command they touch and most leave it where it was, so every listener was being woken dozens of times per flush for no change.
-
In-flight and active-queue counts are taken over distinct queues, so one registered under a create and a patch no longer reports double what it is doing.
-
flushAllvisits each queue once rather than once per command type it is registered under. The repeats were no-ops, but they made the walk several times longer than it needed to be and the ordering log unreadable.
-
-
0.3.014 Aug 2026Release notes
Open source →-
Retry backoff is now scheduled rather than slept.
flush()processes the commands that are due and returns; a command that fails waits for its backoff between flushes instead of inside one.Previously the delay was awaited inside
_processCommandwhile the flush loop kept re-selecting the same command, so a single failing command held its queue for its entire retry ladder — minutes under the default policy — and, for consumers that flush queues in sequence, held every queue behind it too.Retry pacing is unchanged: the same policy produces the same intervals. What changes is that the caller is no longer blocked across them, so flushes need to be driven often enough to pick commands up as they come due. Connectivity changes, app resume, and user-triggered syncs are usually enough;
nextDueAtis there for consumers that would rather schedule a timer. -
Added
ApiCommandQueue.nextAttemptAtandnextDueAt, so a consumer can tell when a command is next eligible and when to flush again. -
Time is now read through
package:clock, so retry scheduling can be driven byfake_asyncin tests. No behavioural change outside tests. -
SyncState.fromJsonno longer throws on state it can only partly read.An unrecognised or wrongly typed
flushStatusnow reads asQueueFlushStatus.idle, and a command bucket that is not a map is skipped with the other bucket left intact. Both are reported throughapiCommandQueueLogger.Previously either would throw, and a consumer persisting the state had no say in what that cost:
hydrated_bloccatches the error, falls back to an empty queue and, by default, writes that back over the stored copy.flushStatusin particular records whether a flush happened to be running when the state was written — worth nothing on restore, but able to destroy every queued command alongside it.Command buckets are also read as
Maprather than cast toMap<String, dynamic>, so a storage backend handing them back loosely typed no longer fails the restore.
-
-
0.2.005 May 2026Release notes
Open source →- Added terminal failure predicates for queue-wide and command-specific non-retryable API failures.
- Added
ApiCommandTerminalFailureRulefor reusable status, data, error, and full-response matching. - Documented terminal failure usage and expanded the package example.
-
0.1.019 Apr 2026