Skip to content

v0.2.1

Choose a tag to compare

@miinhho miinhho released this 12 Sep 04:23
· 8 commits to main since this release
c1571d1

This release separates early value publication from a Job’s full structured lifetime, adds explicit descendant-control APIs, and removes per-child abort listeners.

Early Job value publication

A Job can now publish one typed value before its body and descendants fully settle.

const release = Promise.withResolvers<void>();

const job = new Job<number, string>(async (publish) => {
  publish("ready");
  await release.promise;
  return 42;
}).start();

console.log(await job.value()); // "ready"

release.resolve();
console.log(await job); // 42
  • Added Job<T, Published = T>.
  • Added the one-shot publish(value) body argument.
  • Added job.value() for observing the published value.
  • Publication remains available after cancellation while the body is still running.
  • job.value() and the final Job result remain independent.
  • Published-value types propagate through Supervisor and TaskGroup APIs.

Descendant lifecycle control

  • Added job.cancelChildren(reason?).
    • Cancels direct children.
    • Cascades cancellation through their descendants.
    • Waits for the cancelled child lifetimes to settle.
    • Does not cancel the owning Job or prevent later child admission.
  • Added job.reconcileFailure(error).
    • Reconciles a caught rejection with genuine descendant failures already recorded by the Job.
    • Preserves independent failures together as an AggregateError.

Cancellation performance and reliability

  • Removed the parent AbortSignal listener previously installed for every child Job.
  • Parent cancellation now uses the Job ownership tree directly.
  • External cancellation listeners are deduplicated and released after the complete Job lifetime drains.
  • Cancellation sources and deadline timers are no longer registered after cancellation has already been committed.
  • Reentrant cancellation during listener registration no longer admits unnecessary subsequent bindings.
  • Descendant cancellation now uses iterative traversal, avoiding call-stack exhaustion for deeply nested Job trees.

A smoke measurement with 10,000 live children confirmed:

  • 0 child-installed listeners on the parent signal.
  • 1 listener on an external cancellation source.
  • Cancellation still propagates through the complete ownership tree.

Compatibility

No intentional breaking API changes. Existing Job<T> usage remains valid because the published-value type defaults to the Job result type.

Changes

  • #17 (#17) Separate Job values from lifetime
  • #18 (#18) Remove parent-child abort listeners
  • #19 (#19) Harden cancellation binding lifecycle
  • #20 (#20) Version 0.2.1

Full Changelog: v0.2.0...v0.2.1