diff --git a/fleetd/src/test/java/dev/ltms/fleet/msg/MessageServiceTest.java b/fleetd/src/test/java/dev/ltms/fleet/msg/MessageServiceTest.java index d965d10..c3dca80 100644 --- a/fleetd/src/test/java/dev/ltms/fleet/msg/MessageServiceTest.java +++ b/fleetd/src/test/java/dev/ltms/fleet/msg/MessageServiceTest.java @@ -393,6 +393,56 @@ class MessageServiceTest { * never made answerable again, and (2) the async ticket still resolves {@code DONE} once the * worker's real {@code fleet_reply} lands — it is never stranded {@code PENDING}. */ + /** + * fleetd #334 gated the ask-timeout teardown on {@code ticket.fresh()}, matching the {@code + * finally} block that already did. This pins that gate. A coalesced duplicate passes its own + * {@code timeoutMillis}, which says nothing about whether the shared ask is done — so a + * duplicate timing out first must leave the fresh owner's still-open ask answerable. + * + *
Measured on merge: without this test, removing the {@code ticket.fresh()} gate left all + * 1371 tests green. The gate shipped with the reorder and nothing held it there. + * + *
What this does not prove: anything about the ordering inside the gate — that is
+ * {@code aLateAnswerDuringAskTimeoutTeardownStillCompletesTheAsyncTicket}'s job.
+ */
+ @Test
+ void aCoalescedDuplicateAskTimingOutLeavesTheFreshOwnersAskOpen() throws Exception {
+ String ticket = messages.sendAsync(T, "long task");
+ awaitWaiting();
+ injector.onStatus(T, AgentStatus.IDLE); // deliver
+ injector.onStatus(T, AgentStatus.WORKING); // worker picks it up, then pauses to ask
+
+ CompletableFuture