refactor(chat): remove guest history synchronization

This commit is contained in:
2026-07-20 14:02:39 +08:00
parent 1f7ab2be04
commit 4d1c85727a
17 changed files with 10 additions and 300 deletions
@@ -1,84 +0,0 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { Result } from "@/utils/result";
const mocks = vi.hoisted(() => ({
getDeviceId: vi.fn(),
getLocalMessages: vi.fn(),
syncGuestHistory: vi.fn(),
clearLocalMessages: vi.fn(),
getGuestChatOwnerKey: vi.fn(),
}));
vi.mock("@/data/storage/auth", () => ({
AuthStorage: {
getInstance: () => ({ getDeviceId: mocks.getDeviceId }),
},
}));
vi.mock("@/data/repositories/chat_repository_loader", () => ({
loadChatRepository: async () => ({
getLocalMessages: mocks.getLocalMessages,
syncGuestHistory: mocks.syncGuestHistory,
clearLocalMessages: mocks.clearLocalMessages,
}),
}));
vi.mock("@/data/storage/navigation", () => ({
NavigationStorage: {
getGuestChatOwnerKey: mocks.getGuestChatOwnerKey,
},
}));
import { syncGuestHistoriesToUser } from "../guest-history-sync";
describe("syncGuestHistoriesToUser", () => {
beforeEach(() => {
vi.clearAllMocks();
mocks.getDeviceId.mockResolvedValue(Result.ok("device-1"));
mocks.getGuestChatOwnerKey.mockResolvedValue(null);
mocks.clearLocalMessages.mockResolvedValue(Result.ok(undefined));
});
it("groups guest history by character and clears only successful caches", async () => {
mocks.getLocalMessages.mockImplementation(async (identity: string) =>
Result.ok([
{
id: `${identity}:message`,
role: "user",
type: "text",
content: identity,
createdAt: "2026-07-20T00:00:00.000Z",
},
]),
);
mocks.syncGuestHistory.mockImplementation(
async (request: { characterId: string }) =>
request.characterId === "elio"
? Result.ok(undefined)
: Result.err(new Error("offline")),
);
await syncGuestHistoriesToUser(["elio", "maya-tan"]);
expect(mocks.syncGuestHistory).toHaveBeenCalledTimes(2);
expect(mocks.syncGuestHistory).toHaveBeenCalledWith(
expect.objectContaining({ characterId: "elio" }),
);
expect(mocks.syncGuestHistory).toHaveBeenCalledWith(
expect.objectContaining({ characterId: "maya-tan" }),
);
expect(mocks.clearLocalMessages).toHaveBeenCalledOnce();
expect(mocks.clearLocalMessages).toHaveBeenCalledWith(
"device:device-1::character:elio",
);
});
it("skips characters without guest messages", async () => {
mocks.getLocalMessages.mockResolvedValue(Result.ok([]));
await syncGuestHistoriesToUser(["elio"]);
expect(mocks.syncGuestHistory).not.toHaveBeenCalled();
});
});
-65
View File
@@ -1,65 +0,0 @@
import { AuthStorage } from "@/data/storage/auth";
import { NavigationStorage } from "@/data/storage/navigation";
import { loadChatRepository } from "@/data/repositories/chat_repository_loader";
import { ChatSyncRequestSchema } from "@/data/schemas/chat";
import { buildChatConversationKey } from "@/lib/chat/chat_cache_keys";
import { Logger } from "@/utils/logger";
import { Result } from "@/utils/result";
const log = new Logger("StoresChatGuestHistorySync");
export async function syncGuestHistoriesToUser(
characterIds: readonly string[],
): Promise<void> {
const deviceResult = await AuthStorage.getInstance().getDeviceId();
const savedOwnerKey = await NavigationStorage.getGuestChatOwnerKey();
const ownerKey =
savedOwnerKey ??
(Result.isOk(deviceResult) && deviceResult.data
? `device:${deviceResult.data}`
: null);
if (!ownerKey) return;
const repository = await loadChatRepository();
await Promise.allSettled(
[...new Set(characterIds)].map(async (characterId) => {
const cacheIdentity = buildChatConversationKey(ownerKey, characterId);
const messagesResult = await repository.getLocalMessages(cacheIdentity);
if (Result.isErr(messagesResult) || messagesResult.data.length === 0) return;
const messages = messagesResult.data.flatMap((message) => {
if (message.role !== "user" && message.role !== "assistant") return [];
return [{
role: message.role,
content: message.content,
timestamp: normalizeTimestamp(message.createdAt),
}];
});
if (messages.length === 0) return;
const request = ChatSyncRequestSchema.parse({ characterId, messages });
const syncResult = await repository.syncGuestHistory(request);
if (Result.isErr(syncResult)) {
log.warn("[chat-sync] guest history sync failed", {
characterId,
error: syncResult.error,
});
return;
}
const clearResult = await repository.clearLocalMessages(cacheIdentity);
if (Result.isErr(clearResult)) {
log.warn("[chat-sync] guest history cleanup failed", {
characterId,
error: clearResult.error,
});
}
}),
);
}
function normalizeTimestamp(value: string): string {
const parsed = new Date(value);
return Number.isNaN(parsed.getTime())
? new Date().toISOString()
: parsed.toISOString();
}