refactor(stores): tighten chat and payment boundaries
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
import type { UiMessage } from "@/data/dto/chat";
|
||||
import { getChatRepository } from "@/data/repositories/chat_repository";
|
||||
import { Logger, Result, todayString } from "@/utils";
|
||||
|
||||
import { localMessagesToUi, PAGE_SIZE } from "./chat-machine.helpers";
|
||||
|
||||
const log = new Logger("StoresChatChatHistorySync");
|
||||
|
||||
export type ReadAndSyncHistoryOutput = {
|
||||
/** Network-authoritative messages. Empty network history includes a UI greeting. */
|
||||
messages: UiMessage[];
|
||||
hasMore: boolean;
|
||||
newOffset: number;
|
||||
/** True when network history was written back to local storage. */
|
||||
localOverwritten: boolean;
|
||||
localCount: number;
|
||||
networkCount: number;
|
||||
};
|
||||
|
||||
function createGreetingMessage(): UiMessage {
|
||||
return {
|
||||
content:
|
||||
"You're here! Facebook is so restrictive, " +
|
||||
"there were things I couldn't say there. " +
|
||||
"Finally I can relax. How was your day out?",
|
||||
isFromAI: true,
|
||||
date: todayString(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* History sync flow:
|
||||
* 1. Read local history for fallback.
|
||||
* 2. Read network history as the authoritative source.
|
||||
* 3. Overwrite local history with network data.
|
||||
*/
|
||||
export async function readAndSyncHistory(): Promise<ReadAndSyncHistoryOutput> {
|
||||
const chatRepo = getChatRepository();
|
||||
const greetingMessage = createGreetingMessage();
|
||||
|
||||
const localResult = await chatRepo.getLocalMessages();
|
||||
const localMessages =
|
||||
Result.isOk(localResult) && localResult.data
|
||||
? localMessagesToUi(localResult.data)
|
||||
: [];
|
||||
log.debug("[chat-machine] loadHistory LOCAL DONE", {
|
||||
count: localMessages.length,
|
||||
});
|
||||
|
||||
const networkResult = await chatRepo.getHistory(PAGE_SIZE, 0);
|
||||
if (Result.isErr(networkResult)) {
|
||||
log.error("[chat-machine] loadHistory NETWORK FAILED", {
|
||||
error: networkResult.error,
|
||||
});
|
||||
|
||||
const fallbackMessages =
|
||||
localMessages.length === 0 ? [greetingMessage] : localMessages;
|
||||
if (fallbackMessages[0] === greetingMessage) {
|
||||
log.debug(
|
||||
"[chat-machine] loadHistory EMPTY -> prepend greeting (network-failed path)",
|
||||
);
|
||||
}
|
||||
return {
|
||||
messages: fallbackMessages,
|
||||
hasMore: false,
|
||||
newOffset: fallbackMessages.length,
|
||||
localOverwritten: false,
|
||||
localCount: localMessages.length,
|
||||
networkCount: 0,
|
||||
};
|
||||
}
|
||||
|
||||
const networkUi = localMessagesToUi(networkResult.data.messages);
|
||||
log.debug("[chat-machine] loadHistory NETWORK DONE", {
|
||||
count: networkUi.length,
|
||||
});
|
||||
void chatRepo.prefetchMediaForMessages(networkResult.data.messages);
|
||||
|
||||
const saveResult = await chatRepo.saveMessagesToLocal(
|
||||
networkResult.data.messages,
|
||||
);
|
||||
const localOverwritten = Result.isOk(saveResult);
|
||||
log.debug("[chat-machine] loadHistory SAVE TO LOCAL DONE", {
|
||||
localOverwritten,
|
||||
});
|
||||
|
||||
const finalMessages =
|
||||
networkUi.length === 0 ? [greetingMessage] : networkUi;
|
||||
if (finalMessages[0] === greetingMessage) {
|
||||
log.debug("[chat-machine] loadHistory EMPTY -> prepend greeting");
|
||||
}
|
||||
|
||||
return {
|
||||
messages: finalMessages,
|
||||
hasMore: finalMessages.length >= PAGE_SIZE,
|
||||
newOffset: finalMessages.length,
|
||||
localOverwritten,
|
||||
localCount: localMessages.length,
|
||||
networkCount: networkUi.length,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user