Fix 500 on reservation edit after DB reinit (issue #883)

saveEndpoints was bound at module load via db.transaction(...). When the
demo-mode hourly reset (or a self-hoster's backup restore) closes the DB
connection and reinitialises it, the bound transaction still references
the now-closed connection — every subsequent reservation save with an
endpoints field throws "The database connection is not open", which the
client surfaces as "Internal server error".

Bind the transaction lazily on each call so it always runs against the
current connection.
This commit is contained in:
Maurice
2026-04-26 12:14:17 +02:00
parent 35ed712d46
commit cb425fb397
+17 -9
View File
@@ -61,16 +61,24 @@ function resolveDayIdFromTime(
return row?.id ?? null; return row?.id ?? null;
} }
const saveEndpoints = db.transaction((reservationId: number, endpoints: EndpointInput[]) => { function saveEndpoints(reservationId: number, endpoints: EndpointInput[]): void {
db.prepare('DELETE FROM reservation_endpoints WHERE reservation_id = ?').run(reservationId); // Bind the transaction lazily on each call. Binding at module load time
const insert = db.prepare(` // captures the DB connection that was open then, which becomes invalid
INSERT INTO reservation_endpoints (reservation_id, role, sequence, name, code, lat, lng, timezone, local_time, local_date) // after demo-reset / restore-from-backup closes and reinitialises the
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) // connection — every later endpoint save would throw
`); // "The database connection is not open".
endpoints.forEach((e, i) => { const tx = db.transaction((rid: number, eps: EndpointInput[]) => {
insert.run(reservationId, e.role, e.sequence ?? i, e.name, e.code ?? null, e.lat, e.lng, e.timezone ?? null, e.local_time ?? null, e.local_date ?? null); db.prepare('DELETE FROM reservation_endpoints WHERE reservation_id = ?').run(rid);
const insert = db.prepare(`
INSERT INTO reservation_endpoints (reservation_id, role, sequence, name, code, lat, lng, timezone, local_time, local_date)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
eps.forEach((e, i) => {
insert.run(rid, e.role, e.sequence ?? i, e.name, e.code ?? null, e.lat, e.lng, e.timezone ?? null, e.local_time ?? null, e.local_date ?? null);
});
}); });
}); tx(reservationId, endpoints);
}
export function listReservations(tripId: string | number) { export function listReservations(tripId: string | number) {
const reservations = db.prepare(` const reservations = db.prepare(`