Isolate project device sync transactions

This commit is contained in:
2026-07-23 18:57:18 +02:00
parent cf356bbedc
commit 91baa6c76c
10 changed files with 414 additions and 126 deletions
+5 -55
View File
@@ -1,8 +1,6 @@
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { ProjectDeviceSyncService } from "../src/domain/services/project-device-sync.service.js";
import { CircuitDeviceRowRepository } from "../src/db/repositories/circuit-device-row.repository.js";
import { db } from "../src/db/client.js";
function projectDevice() {
return {
@@ -72,14 +70,16 @@ function createService() {
async listLinkStatesByIds() {
return rows.map((row) => ({ id: row.id, linkedProjectDeviceId: row.linkedProjectDeviceId })) as never;
},
updateLinkedRowsTransactional(_projectDeviceId, changes) {
} as never,
deviceRowSyncStore: {
updateLinkedRows(_projectDeviceId, changes) {
transactionCalls += 1;
for (const change of changes) {
updates.push({ rowId: change.rowId, ...change.input });
Object.assign(rows.find((row) => row.id === change.rowId)!, change.input);
}
},
disconnectLinkedRowsTransactional(_projectDeviceId, rowIds) {
disconnectLinkedRows(_projectDeviceId, rowIds) {
transactionCalls += 1;
for (const rowId of rowIds) {
const row = rows.find((entry) => entry.id === rowId)!;
@@ -87,7 +87,7 @@ function createService() {
Object.assign(row, { linkedProjectDeviceId: null });
}
},
reconnectRowsTransactional(projectDeviceId, rowIds) {
reconnectRows(projectDeviceId, rowIds) {
transactionCalls += 1;
for (const rowId of rowIds) {
Object.assign(rows.find((row) => row.id === rowId)!, { linkedProjectDeviceId: projectDeviceId });
@@ -160,54 +160,4 @@ describe("project device synchronization", () => {
assert.equal(rows[0].linkedProjectDeviceId, "pd1");
});
it("executes multi-row updates inside one synchronous transaction", () => {
const repository = new CircuitDeviceRowRepository();
const originalTransaction = (db as unknown as { transaction: unknown }).transaction;
let transactionCalls = 0;
let updateCalls = 0;
let returnedPromise = false;
(db as unknown as { transaction: (callback: (tx: unknown) => unknown) => void }).transaction = (callback) => {
transactionCalls += 1;
const fakeTx = {
update() {
return {
set() {
return {
where() {
return {
run() {
updateCalls += 1;
return { changes: 1 };
},
};
},
};
},
};
},
};
const result = callback(fakeTx);
returnedPromise = Boolean(result && typeof (result as Promise<unknown>).then === "function");
};
try {
const input = {
linkedProjectDeviceId: "pd1",
name: "Luminaire",
displayName: "Office lighting",
quantity: 1,
powerPerUnit: 0.1,
simultaneityFactor: 1,
};
repository.updateLinkedRowsTransactional("pd1", [
{ rowId: "r1", input },
{ rowId: "r2", input },
]);
assert.equal(transactionCalls, 1);
assert.equal(updateCalls, 2);
assert.equal(returnedPromise, false);
} finally {
(db as unknown as { transaction: unknown }).transaction = originalTransaction;
}
});
});