ADR 0007: Remote Ask Protocol Standards
Status
Accepted
Context
Remote ask() requires explicit protocol rules for correlation and deduplication, timeout and cancellation races, retry behavior under packet loss, and bounded memory for terminal request state. Without a written standard, behavior drifts across refactors.
Decision
The worker pool ask protocol is standardized as follows.
1. Correlation and IDs
- Every remote ask request is identified by mandatory
Envelope.requestId. correlationIdandcausationIdare propagated unchanged across request/reply control frames.- Caller-side pending map key is
requestId.
2. Control messages
All are transported as envelope payloads via WorkerTransport (no serializer — objects pass directly).
3. Inbound state machine
State enum: InProgress, Replied, Cancelled
Transitions:
null → InProgress: first accepted requestInProgress → Replied: first accepted reply emissionInProgress → Cancelled: cancel received before replyRepliedandCancelledare terminal
Terminal precedence:
- First terminal state wins.
- Late replies after
Cancelledare suppressed (must not sendWorkerAskReply).
4. Dedup semantics
- Duplicate request in
InProgress: respond withWorkerAskAck. - Duplicate request in
Replied: replay cachedWorkerAskReply. - Duplicate request in
Cancelled: replyWorkerAskCancelled. - Duplicate reply/cancel at caller: ignored after pending request is resolved.
5. Caller retry + ack
- Caller sends initial
WorkerAskRequestimmediately. - Caller retries request up to configured max attempts until one of:
WorkerAskAckreceived, or a terminal outcome (reply/cancelled/timeout/local cancel). - Retry timer is cancelled as soon as ack is observed.
6. Timeout and cancel
- Caller timeout fails future with
AskTimeoutException, then sends best-effortWorkerAskCancel. - Local
Future::cancel()sends best-effortWorkerAskCancel. - Remote cancel does not forcibly interrupt actor computation; the protocol guarantees only terminal outcome handling and late-reply suppression.
7. Bounded memory requirements
Inbound terminal caches (state/request/reply) must be bounded by:
- TTL eviction (
INBOUND_TERMINAL_TTL_SECONDS) - max-entry eviction (
INBOUND_TERMINAL_MAX_ENTRIES)
Eviction applies only to terminal entries.
Consequences
Positive
- Deterministic race behavior under reply/cancel/timeout overlap.
- Safer retries with explicit ack stop condition.
- Bounded terminal cache growth for long-running nodes.
Trade-offs
- Slightly more protocol complexity than a simple fire-and-forget ask.
- Actor-side work is not hard-cancelled by remote cancel in the current model.