fix(chat): isolate pending flows and cancel stale requests

This commit is contained in:
2026-07-17 19:22:01 +08:00
parent 2fc312b5c7
commit 8bb1e21886
27 changed files with 501 additions and 92 deletions
+20 -10
View File
@@ -4,6 +4,7 @@ import { loadChatRepository } from "@/data/repositories/chat_repository_loader";
import { resolveChatConversationKey } from "@/data/repositories/chat_cache_identity";
import { Logger } from "@/utils/logger";
import { Result } from "@/utils/result";
import { isAbortError } from "@/utils/abort";
import { readAndSyncHistory } from "../../chat-history-sync";
import {
@@ -25,17 +26,21 @@ export interface UnlockHistoryOutput {
export const unlockHistoryActor = fromPromise<
UnlockHistoryOutput,
{ characterId: string }
>(async ({ input }) => {
>(async ({ input, signal }) => {
const chatRepo = await loadChatRepository();
const unlockResult = await chatRepo.unlockHistory(input.characterId);
const unlockResult = await chatRepo.unlockHistory(input.characterId, {
signal,
});
if (Result.isErr(unlockResult)) {
if (isAbortError(unlockResult.error)) throw unlockResult.error;
log.error("[chat-machine] unlockHistoryActor failed", {
error: unlockResult.error,
});
throw unlockResult.error;
}
const history = await readAndSyncHistory(input.characterId);
signal.throwIfAborted();
const history = await readAndSyncHistory(input.characterId, signal);
return {
unlocked: unlockResult.data.unlocked,
reason: unlockResult.data.reason,
@@ -47,18 +52,22 @@ export const unlockHistoryActor = fromPromise<
export const unlockMessageActor = fromPromise<
UnlockMessageOutput,
UnlockMessageRequest & { characterId: string }
>(async ({ input }) => {
>(async ({ input, signal }) => {
const chatRepo = await loadChatRepository();
const cacheIdentityResult = await resolveChatConversationKey(
input.characterId,
);
const unlockResult = await chatRepo.unlockPrivateMessage({
characterId: input.characterId,
...(input.messageId ? { messageId: input.messageId } : {}),
...(input.lockType ? { lockType: input.lockType } : {}),
...(input.clientLockId ? { clientLockId: input.clientLockId } : {}),
});
const unlockResult = await chatRepo.unlockPrivateMessage(
{
characterId: input.characterId,
...(input.messageId ? { messageId: input.messageId } : {}),
...(input.lockType ? { lockType: input.lockType } : {}),
...(input.clientLockId ? { clientLockId: input.clientLockId } : {}),
},
{ signal },
);
if (Result.isErr(unlockResult)) {
if (isAbortError(unlockResult.error)) throw unlockResult.error;
log.error("[chat-machine] unlockMessageActor failed", {
messageId: input.messageId,
clientLockId: input.clientLockId,
@@ -66,6 +75,7 @@ export const unlockMessageActor = fromPromise<
});
throw unlockResult.error;
}
signal.throwIfAborted();
if (
unlockResult.data.unlocked &&