Files
ST-Bionic-Memory-Ecology/tests/persistence-reducer.mjs

217 lines
6.6 KiB
JavaScript

// ST-BME restrained rebirth — Phase 2 persistence reducer tests.
import assert from "node:assert/strict";
import {
PERSISTENCE_EVENT_TYPES,
applyPersistenceRecordToBatchStatus,
buildAcceptedPersistenceStatePatch,
buildBatchPersistenceRecordFromPersistResult,
buildQueuedPersistenceStatePatch,
planAcceptedPendingClear,
reducePersistenceState,
reducePersistenceStatePatch,
} from "../sync/persistence-reducer.js";
const acceptedRecord = buildBatchPersistenceRecordFromPersistResult({
accepted: true,
saved: true,
storageTier: "authority-sql",
reason: "extraction-batch-complete",
revision: 12,
saveMode: "authority-sql",
});
assert.deepEqual(acceptedRecord, {
outcome: "saved",
accepted: true,
recoverable: false,
storageTier: "authority-sql",
reason: "extraction-batch-complete",
revision: 12,
saveMode: "authority-sql",
saved: true,
queued: false,
blocked: false,
});
const recoverableRecord = buildBatchPersistenceRecordFromPersistResult({
accepted: false,
recoverable: true,
storageTier: "metadata-full",
revision: 4,
});
assert.equal(recoverableRecord.outcome, "recoverable");
assert.equal(recoverableRecord.accepted, false);
const chatStateRecord = buildBatchPersistenceRecordFromPersistResult({
accepted: true,
saved: true,
storageTier: "chat-state",
revision: 5,
});
assert.equal(
chatStateRecord.outcome,
"fallback",
"Phase 2 preserves old batch-status wording for chat-state fallback acceptance",
);
console.log(" ✓ persist results reduce to stable batch persistence records");
const acceptedPatch = buildAcceptedPersistenceStatePatch({
currentState: {
lastAcceptedRevision: 9,
queuedPersistRevision: 12,
queuedPersistChatId: "chat-a",
pendingPersist: true,
writesBlocked: true,
lastRecoverableStorageTier: "metadata-full",
},
persistenceRecord: acceptedRecord,
});
assert.equal(acceptedPatch.pendingPersist, false);
assert.equal(acceptedPatch.writesBlocked, false);
assert.equal(acceptedPatch.lastAcceptedRevision, 12);
assert.equal(acceptedPatch.acceptedStorageTier, "authority-sql");
assert.equal(acceptedPatch.lastRecoverableStorageTier, "none");
assert.equal(acceptedPatch.queuedPersistRevision, 0);
assert.equal(acceptedPatch.queuedPersistChatId, "");
const unsafeAcceptedPatch = buildAcceptedPersistenceStatePatch({
currentState: { pendingPersist: true, lastAcceptedRevision: 4 },
persistenceRecord: {
accepted: true,
storageTier: "metadata-full",
revision: 9,
},
});
assert.deepEqual(
unsafeAcceptedPatch,
{},
"recovery-only accepted records must not clear pending state through the reducer",
);
console.log(" ✓ canonical accepted state clears pending and queued fields");
assert.deepEqual(
reducePersistenceStatePatch(
{
lastAcceptedRevision: 9,
pendingPersist: true,
writesBlocked: true,
},
{
type: PERSISTENCE_EVENT_TYPES.ACCEPTED,
persistenceRecord: acceptedRecord,
},
),
buildAcceptedPersistenceStatePatch({
currentState: {
lastAcceptedRevision: 9,
pendingPersist: true,
writesBlocked: true,
},
persistenceRecord: acceptedRecord,
}),
);
const reducedAcceptedState = reducePersistenceState(
{ pendingPersist: true, writesBlocked: true, lastAcceptedRevision: 9, custom: "keep" },
{ type: PERSISTENCE_EVENT_TYPES.ACCEPTED, persistenceRecord: acceptedRecord },
);
assert.equal(reducedAcceptedState.pendingPersist, false);
assert.equal(reducedAcceptedState.custom, "keep");
assert.equal(reducedAcceptedState.acceptedStorageTier, "authority-sql");
console.log(" ✓ accepted persistence state updates are event-reduced patches");
const queuedPatch = buildQueuedPersistenceStatePatch({
currentState: {
queuedPersistRevision: 6,
lastRecoverableStorageTier: "metadata-full",
},
reason: "extraction-batch-complete:pending",
revision: 10,
chatId: "chat-a",
immediate: true,
recoverableTier: "shadow",
});
assert.equal(queuedPatch.pendingPersist, true);
assert.equal(queuedPatch.writesBlocked, false);
assert.equal(queuedPatch.queuedPersistRevision, 10);
assert.equal(queuedPatch.queuedPersistChatId, "chat-a");
assert.equal(queuedPatch.queuedPersistMode, "immediate");
assert.equal(queuedPatch.lastRecoverableStorageTier, "shadow");
const blockedQueuedPatch = buildQueuedPersistenceStatePatch({
currentState: { queuedPersistRevision: 11, lastRecoverableStorageTier: "shadow" },
reason: "authority-down",
revision: 9,
chatId: "chat-a",
recoverableTier: "none",
});
assert.equal(blockedQueuedPatch.queuedPersistRevision, 11);
assert.equal(blockedQueuedPatch.writesBlocked, true);
assert.equal(blockedQueuedPatch.lastRecoverableStorageTier, "shadow");
console.log(" ✓ queued state preserves max revision and recovery-only semantics");
assert.deepEqual(
reducePersistenceStatePatch(
{ queuedPersistRevision: 6, lastRecoverableStorageTier: "metadata-full" },
{
type: PERSISTENCE_EVENT_TYPES.QUEUED,
reason: "extraction-batch-complete:pending",
revision: 10,
chatId: "chat-a",
immediate: true,
recoverableTier: "shadow",
},
),
queuedPatch,
);
assert.deepEqual(reducePersistenceStatePatch({}, { type: "unknown" }), {});
const batchStatus = {
completed: true,
historyAdvanceAllowed: false,
historyAdvanced: false,
persistence: { outcome: "queued" },
};
const nextBatchStatus = applyPersistenceRecordToBatchStatus(batchStatus, acceptedRecord);
assert.notEqual(nextBatchStatus, batchStatus);
assert.equal(nextBatchStatus.persistence.outcome, "saved");
assert.equal(nextBatchStatus.historyAdvanceAllowed, true);
assert.equal(nextBatchStatus.historyAdvanced, true);
const clearPlan = planAcceptedPendingClear({
batchPersistence: { revision: 10, storageTier: "metadata-full" },
persistenceState: {
pendingPersist: true,
queuedPersistRevision: 12,
queuedPersistChatId: "chat-a",
lastAcceptedRevision: 12,
acceptedStorageTier: "authority-sql",
},
activeChatId: "chat-a",
queuedChatId: "chat-a",
});
assert.equal(clearPlan.action, "clear-stale-pending");
const unsafePlan = planAcceptedPendingClear({
batchPersistence: { revision: 10, storageTier: "metadata-full" },
persistenceState: {
pendingPersist: true,
queuedPersistRevision: 12,
queuedPersistChatId: "chat-a",
lastAcceptedRevision: 12,
acceptedStorageTier: "metadata-full",
},
activeChatId: "chat-a",
queuedChatId: "chat-a",
});
assert.equal(unsafePlan.action, "keep");
assert.equal(unsafePlan.reason, "accepted-tier-not-canonical");
console.log(" ✓ accepted pending clear plan keeps canonical-tier invariant");
console.log("persistence-reducer tests passed");