Centralize snapshot restore transactions

This commit is contained in:
2026-07-26 11:35:45 +02:00
parent 214ad728cd
commit 4789e01aac
4 changed files with 42 additions and 46 deletions
@@ -25,8 +25,7 @@ import { legacyConsumerMigrationReports } from "../schema/legacy-consumer-migrat
import { projectDevices } from "../schema/project-devices.js";
import { projects } from "../schema/projects.js";
import { rooms } from "../schema/rooms.js";
import { applyProjectHistoryTransition } from "./project-history.persistence.js";
import { appendProjectRevision } from "./project-revision.persistence.js";
import { executeProjectCommandTransaction } from "./project-command-transaction.persistence.js";
import {
hashProjectStatePayload,
readProjectStateSnapshot,
@@ -43,49 +42,43 @@ export class ProjectStateRestoreCommandRepository
throw new Error("Restore state belongs to a different project.");
}
return this.database.transaction((tx) => {
const current = readProjectStateSnapshot(tx, input.projectId);
if (!current) {
throw new Error("Project not found.");
}
if (
current.payloadSha256 !==
input.command.payload.expectedStateSha256
) {
throw new ProjectStateConflictError(
input.projectId,
input.command.payload.expectedStateSha256,
current.payloadSha256
);
}
return executeProjectCommandTransaction(
this.database,
input,
(tx) => this.applyCommand(tx, input)
);
}
const targetPayloadJson = serializeProjectStateSnapshot(
input.command.payload.targetState
);
const inverse = createProjectStateRestoreCommand(
hashProjectStatePayload(targetPayloadJson),
current.state
private applyCommand(
tx: AppDatabase,
input: ExecuteProjectStateRestoreCommandInput
) {
const current = readProjectStateSnapshot(tx, input.projectId);
if (!current) {
throw new Error("Project not found.");
}
if (
current.payloadSha256 !==
input.command.payload.expectedStateSha256
) {
throw new ProjectStateConflictError(
input.projectId,
input.command.payload.expectedStateSha256,
current.payloadSha256
);
}
replaceProjectState(tx, input.command.payload.targetState);
const targetPayloadJson = serializeProjectStateSnapshot(
input.command.payload.targetState
);
const inverse = createProjectStateRestoreCommand(
hashProjectStatePayload(targetPayloadJson),
current.state
);
const revision = appendProjectRevision(tx, {
projectId: input.projectId,
expectedRevision: input.expectedRevision,
source: input.source,
description: input.description,
actorId: input.actorId,
forward: input.command,
inverse,
});
applyProjectHistoryTransition(tx, {
projectId: input.projectId,
source: input.source,
recordedChangeSetId: revision.changeSetId,
targetChangeSetId: input.historyTargetChangeSetId,
});
return { revision, inverse };
});
replaceProjectState(tx, input.command.payload.targetState);
return inverse;
}
}