fix(queue): clear the queue card after the last queued message is sent
When the server delivered the last item of a session's queue it deleted the session entry and broadcast the update with an empty directory. The UI keys its projection by directory, could not build the key, and dropped the event, so the delivered message stayed in the "Queued messages" card until the next full hydration. The server now remembers a session's directory beyond the emptying of its queue so that broadcast names it. The UI additionally treats an empty session without a directory as "this session's queue is done" for every projection keyed under that session id, which covers clients talking to an older server. Claude-Session: https://claude.ai/code/session_01VqV56Hez25hTxXH4ipJfzH
This commit is contained in:
@@ -429,6 +429,26 @@ const removeMessageLocally = (
|
||||
return { queuedMessages: { ...state.queuedMessages, [key]: newQueue } };
|
||||
};
|
||||
|
||||
/** Every projection of one session in this runtime, whatever directory it was keyed under. */
|
||||
const clearSessionProjection = (
|
||||
state: Pick<MessageQueueState, 'queuedMessages' | 'sendingIds'>,
|
||||
runtimeKey: string,
|
||||
sessionId: string,
|
||||
revision: number,
|
||||
): Pick<MessageQueueState, 'queuedMessages' | 'sendingIds'> => {
|
||||
let queuedMessages = state.queuedMessages;
|
||||
let sendingIds = state.sendingIds;
|
||||
for (const key of new Set([...Object.keys(queuedMessages), ...Object.keys(sendingIds)])) {
|
||||
const parsed = parseMessageQueueKey(key);
|
||||
if (parsed?.runtimeKey !== runtimeKey || parsed.sessionId !== sessionId) continue;
|
||||
if ((appliedRevisions.get(key) ?? -1) > revision) continue;
|
||||
appliedRevisions.set(key, revision);
|
||||
queuedMessages = withoutKey(queuedMessages, key);
|
||||
sendingIds = withoutKey(sendingIds, key);
|
||||
}
|
||||
return { queuedMessages, sendingIds };
|
||||
};
|
||||
|
||||
export const useMessageQueueStore = create<MessageQueueStore>()(
|
||||
devtools(
|
||||
persist(
|
||||
@@ -436,7 +456,14 @@ export const useMessageQueueStore = create<MessageQueueStore>()(
|
||||
const applyServerSession = (session: ServerQueueSession, revision: number, expectedRuntimeKey: string) => {
|
||||
if (expectedRuntimeKey !== getRuntimeKey()) return;
|
||||
const target = createMessageQueueTarget(session.sessionId, session.directory, expectedRuntimeKey);
|
||||
if (!target) return;
|
||||
if (!target) {
|
||||
// Servers before 1.22.2 drop a session's directory once its
|
||||
// queue is empty. A session id is unique across directories,
|
||||
// so an empty session still says which projection is done.
|
||||
if (session.items.length > 0) return;
|
||||
set((state) => clearSessionProjection(state, expectedRuntimeKey, session.sessionId, revision));
|
||||
return;
|
||||
}
|
||||
const key = getMessageQueueKey(target);
|
||||
if ((appliedRevisions.get(key) ?? -1) > revision) return;
|
||||
appliedRevisions.set(key, revision);
|
||||
|
||||
Reference in New Issue
Block a user