Skip to content

AsyncResolutionBatcher

Defined in: packages/engine/src/engine/AsyncResolutionBatcher.ts:81

Micro-batches async resolution completions into a single DAG walk + re-evaluation pass.

When multiple promises resolve within the same event-loop tick (e.g., 3 currency rates: USD→GBP, USD→EUR, USD→JPY all return within 2ms), this batcher collapses them into ONE DAG walk and ONE re-execution pass instead of 3 separate ones.

Lifecycle:

  • Engine calls add() after each resolveAsync() completes
  • queueMicrotask() schedules flush() for the end of the current tick
  • flush() deduplicates queryKeys, walks DAG once for all resolved keys, topologically sorts affected lines, re-executes, and fires listener events

Perf: For N resolutions in a tick, reduces DAG walks from N to 1 and re-executions from N*avgAffected to totalAffected.

* Events are published to a native ReadableStream. Stream-based
  • consumers read from the stream via getReader(), gaining built-in
  • cancellation (reader.cancel()), proper resource cleanup
  • (reader.releaseLock()), and the ability to
  • pipeTo() / pipeThrough() / tee() the event flow.

The stream uses a configurable CountQueuingStrategy with a default highWaterMark of 64 events to limit the internal buffer size.

new AsyncResolutionBatcher(
dag,
lineCache,
vm,
highWaterMark?): AsyncResolutionBatcher;

Defined in: packages/engine/src/engine/AsyncResolutionBatcher.ts:181

ParameterTypeDefault value
dagDependencyGraphundefined
lineCacheLineCacheundefined
vmVMundefined
highWaterMarknumberAsyncResolutionBatcher.DEFAULT_HIGH_WATER_MARK

AsyncResolutionBatcher

_testCaptures:
| AsyncResolutionEvent[]
| null = null;

Defined in: packages/engine/src/engine/AsyncResolutionBatcher.ts:131

Test-only synchronous capture array. When enabled (non-null), every event is synchronously pushed here in addition to the stream. Tests read from this array to avoid async stream reader timing issues.


onLineResult: ((lineNumber, value) => void) | null = null;

Defined in: packages/engine/src/engine/AsyncResolutionBatcher.ts:149

Called for each line whose result is patched after an async resolution, on both the main-thread and worker-pool paths.

A host that displays async results must set this. It is the only mechanism that moves a resolved value out of the LineCache and into the host’s own document state. The engine cannot do it itself: it does not own a document, the host does, and the batcher has no reference to one.

Nullable rather than a constructor parameter because it is cleared by clearAll() and re-wired on re-subscribe, so it cannot be readonly. That makes it easy to miss, which is why warnIfUnwired exists: leaving it unset means async values resolve into the cache and are never shown, with nothing to indicate why. A host that genuinely does not want async results should not register async resolvers at all.

get dedupCount(): number;

Defined in: packages/engine/src/engine/AsyncResolutionBatcher.ts:278

Number of pending entries collapsed by (packageId, queryKey) deduplication.

number


get listenerCount(): number;

Defined in: packages/engine/src/engine/AsyncResolutionBatcher.ts:291

Whether the internal event stream currently has an active reader. 1 if a consumer has called getEventStream().getReader() (or otherwise locked the stream) and not released it, 0 otherwise.

number


get pendingCount(): number;

Defined in: packages/engine/src/engine/AsyncResolutionBatcher.ts:273

Number of resolutions currently queued for the next flush.

number


get workerOffloadCount(): number;

Defined in: packages/engine/src/engine/AsyncResolutionBatcher.ts:296

Number of flushes that were actually dispatched to the worker pool.

number

add(entry): void;

Defined in: packages/engine/src/engine/AsyncResolutionBatcher.ts:220

Add a resolved query key to the pending batch.

Called by ExpressionEngine.resolveAsync() after a promise resolves or errors. If this is the first entry in the current tick, schedules a microtask flush.

ParameterType
entryBatchEntry

void


clearAll(): void;

Defined in: packages/engine/src/engine/AsyncResolutionBatcher.ts:301

Remove all listeners and cancel pending batch. Called on engine clear.

void


getEventStream(): ReadableStream<AsyncResolutionEvent>;

Defined in: packages/engine/src/engine/AsyncResolutionBatcher.ts:268

Get the native event stream for stream-based consumers.

Use this for backpressure, cancellation, or the ability to pipeTo() / pipeThrough() the event flow.

ReadableStream<AsyncResolutionEvent>

A ReadableStream that emits AsyncResolutionEvent items as the batcher processes async resolutions.