Skip to content

Commit 8760ca7

Browse files
authored
refactor(mothership): a saved Stop handoff's id wins on restore (#8747)
When an entry saved with an id on its Stop handoff also has its own resumeUserMessageId, the handoff's id is the one that build sent, so it is the one kept. resumeUserMessageId's doc names every path that sets it.
1 parent 5d3806b commit 8760ca7

3 files changed

Lines changed: 25 additions & 8 deletions

File tree

‎apps/sim/stores/mothership-queue/store.dom.test.ts‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ describe('useMothershipQueueStore rehydration', () => {
7777
expect(plain?.admissionUnknown).toBeUndefined()
7878
})
7979

80-
it('moves the reused id a saved Stop handoff carried onto the entry', async () => {
80+
it('moves the reused id a saved Stop handoff carried onto the entry, over its own', async () => {
8181
const seed = { chatId: 'chat-A', supersededStreamId: 'previous-response', stopRequired: true }
8282
sessionStorage.setItem(
8383
'mothership-queue',
@@ -96,6 +96,12 @@ describe('useMothershipQueueStore rehydration', () => {
9696
admissionUnknown: false,
9797
queuedSendHandoff: { id: 'never-sent', ...seed, userMessageId: 'attempt-2' },
9898
},
99+
{
100+
id: 'both',
101+
content: 'c',
102+
resumeUserMessageId: 'withdrawn-attempt',
103+
queuedSendHandoff: { id: 'both', ...seed, userMessageId: 'send-now-attempt' },
104+
},
99105
],
100106
},
101107
},
@@ -120,6 +126,14 @@ describe('useMothershipQueueStore rehydration', () => {
120126
admissionUnknown: false,
121127
queuedSendHandoff: { id: 'never-sent', ...seed },
122128
},
129+
{
130+
id: 'both',
131+
content: 'c',
132+
/** The id that build sent: the handoff's, ahead of the entry's. */
133+
resumeUserMessageId: 'send-now-attempt',
134+
admissionUnknown: true,
135+
queuedSendHandoff: { id: 'both', ...seed },
136+
},
123137
])
124138
})
125139
})

‎apps/sim/stores/mothership-queue/store.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,13 @@ function withCurrentWaitFields(value: unknown): unknown {
8585
if (!record) return value
8686
const { retryRequired, heldUntilOnline, sendRetries, notBefore, ...rest } = record
8787
/* An entry saved when its Stop handoff carried the reused id: that id is the
88-
entry's `resumeUserMessageId` now. */
88+
entry's `resumeUserMessageId` now. It wins over the entry's own, as it did
89+
when that build picked the id to send. */
8990
const seed = toRecordOrNull(rest.queuedSendHandoff)
9091
if (seed && typeof seed.userMessageId === 'string') {
9192
const { userMessageId: seedRequestId, ...seedRest } = seed
9293
rest.queuedSendHandoff = seedRest
93-
if (rest.resumeUserMessageId === undefined) rest.resumeUserMessageId = seedRequestId
94+
rest.resumeUserMessageId = seedRequestId
9495
}
9596
return {
9697
...rest,

‎apps/sim/stores/mothership-queue/types.ts‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@ export type QueuedMothershipMessage = QueuedMessage & {
3434
*/
3535
retry?: SendRetry
3636
/**
37-
* Message id of a prior attempt at this send that an unmount cleanup
38-
* withdrew. Reused when the entry is dispatched so the server deduplicates
39-
* against that attempt — it never sees the client's abort, so a request it
40-
* had already accepted still opened the chat and billed the turn. Persisted,
41-
* so a retry after a reload deduplicates too.
37+
* Message id of an earlier attempt at this send, the one id it goes out
38+
* under: a send an unmount cleanup withdrew, a Send-now restored from its
39+
* stored Stop handoff, or a dispatch put back in the queue. Reused when the
40+
* entry is dispatched so the server deduplicates against that attempt — it
41+
* never sees the client's abort, so a request it had already accepted still
42+
* opened the chat and billed the turn. Persisted, so a retry after a reload
43+
* deduplicates too.
4244
*/
4345
resumeUserMessageId?: string
4446
}

0 commit comments

Comments
 (0)