Skip to content

Pace by queue depth

The queue as a marketSDKHTTPsearchByFacetstotalconditional

An upstream step releases new work only while the downstream queue is below a set depth, reading the depth with one counted query.

The situation

Cutting can produce parts faster than packing can handle. Flooding the packing queue hides urgent work under a pile, so cutting should hold back while packing has more than forty items waiting.

The recipe

activities/pacing.ts
export async function packingDepth(): Promise<number> {
const res = await lt.escalations.searchByFacets({ role: 'packing', status: 'pending', limit: 1 });
return res.data?.total ?? 0;
}
workflows/cut-release.ts
const { packingDepth, releaseNextBatch } = Durable.workflow.proxyActivities<typeof activities>({ activities });
export async function cutRelease(envelope: { data: { maxDepth: number } }) {
const depth = await packingDepth();
if (depth < envelope.data.maxDepth) await releaseNextBatch(envelope.data.maxDepth - depth);
await Durable.workflow.sleep('1 minute');
await Durable.workflow.continueAsNew(envelope);
}

The depth is the total of a faceted search over the downstream role. Add facets to pace against a slice, such as one material.

The guarantee

total comes from the same WHERE as the page, so a limit: 1 read is the true count of pending rows the caller can see. Each tick reads live depth, so the release rate follows how fast the downstream role resolves. Machines on a line get the same behavior from queueDepth, enforced by the gateway. See Faceted routing.