fix: stop the composer re-sending a queued message already in flight
A queued message is removed from the queue only after its send resolves, so between dispatch and resolution it stays visible to every reader — and a composer submit merges the whole queue into its own send. Over a relay that window is seconds, long enough to deliver the same message twice. The queue now tracks which entries are awaiting the server. Dispatchers skip them, clearQueue retains them so the pending send can still remove or restore its own entry, and the flag is not persisted because a restart has no in-flight sends.
This commit is contained in:
@@ -221,7 +221,9 @@ export function useQueuedMessageAutoSend(enabledOrOptions?: boolean | { enabled?
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = buildQueuedAutoSendPayload(queueSnapshot);
|
||||
// Read the queue back at dispatch time and skip anything already being
|
||||
// delivered, rather than trusting the render-time snapshot.
|
||||
const payload = buildQueuedAutoSendPayload(useMessageQueueStore.getState().getSendableQueue(target));
|
||||
if (!payload) {
|
||||
return;
|
||||
}
|
||||
@@ -248,6 +250,10 @@ export function useQueuedMessageAutoSend(enabledOrOptions?: boolean | { enabled?
|
||||
}
|
||||
|
||||
inFlightSessionsRef.current.add(targetKey);
|
||||
// The ref only guards this hook. Publish the dispatch to the store so the
|
||||
// composer cannot merge the same item into a parallel send while this one
|
||||
// is still awaiting the server.
|
||||
useMessageQueueStore.getState().markSending(target, payload.queuedMessageId);
|
||||
|
||||
try {
|
||||
await sendQueuedAutoSendPayload(sessionId, target.directory, payload, {
|
||||
@@ -271,6 +277,7 @@ export function useQueuedMessageAutoSend(enabledOrOptions?: boolean | { enabled?
|
||||
retryScheduler.schedule(nextAttemptAt);
|
||||
} finally {
|
||||
inFlightSessionsRef.current.delete(targetKey);
|
||||
useMessageQueueStore.getState().clearSending(target, payload.queuedMessageId);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user