@arki/async
For @arki/[email protected] · source AGENTS.md
AGENTS.md = laws, docs/agent-guide.md = tasks, llms.txt = map.
@arki/async
Timing and structured concurrency on plain Promises and AbortSignal. Read docs/agent-guide.md for tasks. When a doc and the code disagree, src/index.ts wins.
Laws
debounceandthrottlecall the function at the same moments as lodash, with the same arguments. The test replays random schedules against lodash. A change that breaks that replay is a bug, not a new contract.- Time comes from a
Clock(@arki/clock). The default is the system clock. Never callsetTimeoutorDate.nowdirectly insrc/. A test passes aMockClock. - No task outlives the call that started it.
all,mapConcurrentandracesettle only after every started task has settled. - Cancellation is cooperative. Every task gets a
signal. The library never kills code that ignores it, and the docs say so. - Owned scopes close admission, cancel and join admitted work, then run finalizers newest first, one at a time. Every finalizer runs. Returned failures are never resources. A single failure keeps its identity; multiple failures retain exact local primary/cleanup members through
ScopeFailed. scopedandopenScopeinfer typed outcomes from resource/cleanup/child descriptors. Dynamic registrations must fit the scope's canonical definition tuple. Success remains unwrapped. The other timing/concurrency helpers retain their documented rejection contract during the A-33 migration;debounceandthrottlethrowARKI_ASYNC_E001for a bad wait.- Settling cleans up. A finished
sleepleaves no timer and no abort listener behind. - The runtime floor is Hermes. Use no
Promise.withResolvers, noAbortSignal.anyand noasync function*insrc/. Build a linked signal withsrc/signal.ts. - Managed scope boundaries return canonical
@arki/failurevalues for cancellation, deadlines and defects as well as callback refusals. Other helpers retainAsyncError. Every error definition has a stable code, remediation, and JSDoc with@fixand@verify. Aggregate member causes are private; wire revival promises only canonical public data. - A semaphore, mutex or deferred does not belong here. Point readers to
@arki/lockandPromise.withResolvers(). - Never write benchmark numbers by hand.
bun run bench --write-readmewrites them from an idle machine.
Changing this package
- Change the file for the helper:
src/sleep.ts,src/schedule.ts,src/scope.tsorsrc/concurrency.ts. - Add a test next to it for the boundary that decides the behaviour. Use a
MockClockfor time. - A new error code goes in
src/errors.tswith a summary,@fixand@verify. Then runbun ../../tooling/library/src/error-index.tsand check that no entry showsnull. - Update
examples/load-pages.tsonly with its test. The README mirrors itsload-pagesregion, so runarki-doc-examples --writeafter an edit. - Add a changeset in
.changeset/. Documentation-only changes usepatchand the lineno demo impact: documentation and doc-example changes only, runtime behaviour unchanged.
Verify
bun run build
bun run typecheck
bun run test
bun run test:docs
bun run test:runtimes
bun ../../tooling/library/src/error-index.ts
bun ../../tooling/library/src/llms.ts --check