Rebind restored backup history hashes locally

This commit is contained in:
Hao19911125
2026-04-12 11:49:34 +08:00
parent 580a049442
commit 288c33f3c3
2 changed files with 65 additions and 1 deletions

View File

@@ -1105,6 +1105,35 @@ function buildManualBackupSnapshot(snapshot = {}, chatId = "") {
}; };
} }
function markManualBackupHistoryForLocalRebind(snapshot = {}, chatId = "") {
const normalizedSnapshot = normalizeSyncSnapshot(snapshot, chatId);
const meta = toSerializableData(normalizedSnapshot.meta, {});
const historyState = normalizeRuntimeHistoryMeta(
meta[RUNTIME_HISTORY_META_KEY],
chatId,
);
const lastProcessedAssistantFloor = Number(
historyState.lastProcessedAssistantFloor,
);
historyState.processedMessageHashes = {};
historyState.processedMessageHashesNeedRefresh =
Number.isFinite(lastProcessedAssistantFloor) &&
lastProcessedAssistantFloor >= 0;
meta[RUNTIME_HISTORY_META_KEY] = historyState;
return {
meta,
nodes: toSerializableData(normalizedSnapshot.nodes, []),
edges: toSerializableData(normalizedSnapshot.edges, []),
tombstones: toSerializableData(normalizedSnapshot.tombstones, []),
state: toSerializableData(normalizedSnapshot.state, {
lastProcessedFloor: -1,
extractionCount: 0,
}),
};
}
function mergeRuntimeHistoryMeta(localMeta = {}, remoteMeta = {}, options = {}) { function mergeRuntimeHistoryMeta(localMeta = {}, remoteMeta = {}, options = {}) {
const localHistory = normalizeRuntimeHistoryMeta(localMeta, options.chatId); const localHistory = normalizeRuntimeHistoryMeta(localMeta, options.chatId);
const remoteHistory = normalizeRuntimeHistoryMeta(remoteMeta, options.chatId); const remoteHistory = normalizeRuntimeHistoryMeta(remoteMeta, options.chatId);
@@ -2024,7 +2053,10 @@ export async function restoreFromServer(chatId, options = {}) {
}; };
} }
const snapshot = normalizeSyncSnapshot(envelope.snapshot, normalizedChatId); const snapshot = markManualBackupHistoryForLocalRebind(
envelope.snapshot,
normalizedChatId,
);
if (normalizeChatId(snapshot.meta?.chatId) !== normalizedChatId) { if (normalizeChatId(snapshot.meta?.chatId) !== normalizedChatId) {
return { return {
restored: false, restored: false,

View File

@@ -623,6 +623,15 @@ async function testManualBackupAndRestoreFlow() {
chatId: "chat-backup-flow", chatId: "chat-backup-flow",
lastProcessedAssistantFloor: 4, lastProcessedAssistantFloor: 4,
extractionCount: 2, extractionCount: 2,
processedMessageHashVersion: 2,
processedMessageHashes: {
0: "hash-0",
1: "hash-1",
2: "hash-2",
3: "hash-3",
4: "hash-4",
},
processedMessageHashesNeedRefresh: false,
}, },
runtimeBatchJournal: [ runtimeBatchJournal: [
{ id: "journal-1", processedRange: [0, 0], createdAt: 11 }, { id: "journal-1", processedRange: [0, 0], createdAt: 11 },
@@ -677,6 +686,20 @@ async function testManualBackupAndRestoreFlow() {
retainedCount: 4, retainedCount: 4,
}, },
); );
assert.deepEqual(
backupPayload.snapshot.meta.runtimeHistoryState.processedMessageHashes,
{
0: "hash-0",
1: "hash-1",
2: "hash-2",
3: "hash-3",
4: "hash-4",
},
);
assert.equal(
backupPayload.snapshot.meta.runtimeHistoryState.processedMessageHashesNeedRefresh,
false,
);
const backupUploadLog = logs.uploadedPayloads.find( const backupUploadLog = logs.uploadedPayloads.find(
(entry) => entry.name === backupResult.filename, (entry) => entry.name === backupResult.filename,
); );
@@ -725,6 +748,15 @@ async function testManualBackupAndRestoreFlow() {
retainedCount: 4, retainedCount: 4,
}, },
); );
assert.deepEqual(db.snapshot.meta.runtimeHistoryState.processedMessageHashes, {});
assert.equal(
db.snapshot.meta.runtimeHistoryState.processedMessageHashesNeedRefresh,
true,
);
assert.equal(
db.snapshot.meta.runtimeHistoryState.lastProcessedAssistantFloor,
4,
);
assert.ok(Number(db.meta.get("lastBackupRestoredAt")) > 0); assert.ok(Number(db.meta.get("lastBackupRestoredAt")) > 0);
const safetyStatus = await getRestoreSafetySnapshotStatus( const safetyStatus = await getRestoreSafetySnapshotStatus(
"chat-backup-flow", "chat-backup-flow",