Problem
Duroxide currently exposes only blocking dequeueEvent(queueName) for orchestration event queues.
Some orchestrations need to greedily drain already-queued events into their own replay-safe buffer before processing. With the current API, there is no way to ask "is the queue empty right now?" or "pop one event only if something is already queued".
The only available workaround is heuristic:
- repeatedly race
dequeueEvent("messages") against a short timer such as 3s
- if a message wins, buffer it and race again
- if the timer wins, assume the queue is drained enough for this pass
That works, but it is not exact:
- it adds arbitrary latency
- it depends on a magic timeout
- one burst can get split across multiple rounds
- the orchestration cannot distinguish a truly empty queue from a temporarily quiet queue
Concrete use case
PilotSwarm has parent orchestrations that receive a mixed stream of child updates, user prompts, and management messages on the same "messages" queue.
The parent wants to:
- drain already-queued events into a replay-safe KV work buffer
- process that buffered work one item at a time
- avoid
continue_as_new() with a large unmatched-event backlog, because carry-forward overflow can drop messages
Without a non-blocking dequeue primitive, we have to simulate drain completion with a quiet-window timer. That makes correctness and latency depend on the timeout instead of actual queue state.
Proposal
Add a native orchestration primitive such as:
const evt = yield* ctx.tryDequeueEvent("messages");
// evt is null if the queue is currently empty
Semantics:
- returns the next already-queued event if one exists
- returns
null immediately if the named queue is empty
- does not block waiting for future messages
- preserves normal queue ordering
Why this matters
- enables exact drain-until-empty logic
- removes heuristic quiet timers such as 3s races
- lowers latency for bursty workloads
- simplifies queue-to-KV buffering patterns
- makes orchestration behavior more predictable under load
Alternative
If tryDequeueEvent() is not desirable, exposing queue depth / queue-empty state as an orchestration property would also enable this pattern in user code. But a native tryDequeueEvent() would be simpler and safer.
Summary
Today the workaround is: race(dequeueEvent(queue), shortTimer) and assume the queue is drained when the timer wins.
A native tryDequeueEvent() would replace that heuristic with exact semantics.
Problem
Duroxide currently exposes only blocking
dequeueEvent(queueName)for orchestration event queues.Some orchestrations need to greedily drain already-queued events into their own replay-safe buffer before processing. With the current API, there is no way to ask "is the queue empty right now?" or "pop one event only if something is already queued".
The only available workaround is heuristic:
dequeueEvent("messages")against a short timer such as 3sThat works, but it is not exact:
Concrete use case
PilotSwarm has parent orchestrations that receive a mixed stream of child updates, user prompts, and management messages on the same
"messages"queue.The parent wants to:
continue_as_new()with a large unmatched-event backlog, because carry-forward overflow can drop messagesWithout a non-blocking dequeue primitive, we have to simulate drain completion with a quiet-window timer. That makes correctness and latency depend on the timeout instead of actual queue state.
Proposal
Add a native orchestration primitive such as:
Semantics:
nullimmediately if the named queue is emptyWhy this matters
Alternative
If
tryDequeueEvent()is not desirable, exposing queue depth / queue-empty state as an orchestration property would also enable this pattern in user code. But a nativetryDequeueEvent()would be simpler and safer.Summary
Today the workaround is:
race(dequeueEvent(queue), shortTimer)and assume the queue is drained when the timer wins.A native
tryDequeueEvent()would replace that heuristic with exact semantics.