backend/src/versionUtils.js (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
import { MAX_VERSIONS_PER_DOCUMENT } from './messages.js';
import { newId } from './utils.js';
// Autosave fires every second while typing; without coalescing the version
// history fills up with near-identical snapshots within minutes.
export const VERSION_COALESCE_MS = 5 * 60 * 1000;
export function saveDocumentVersion(db, doc, createdAt) {
const versionId = newId();
db.prepare(
`INSERT INTO document_versions (id, document_id, title, mode, content, created_at)
VALUES (?, ?, ?, ?, ?, ?)`,
).run(versionId, doc.id, doc.title, doc.mode, doc.content, createdAt);
const excess = db
.prepare(
`SELECT id FROM document_versions
WHERE document_id = ?
ORDER BY created_at DESC
LIMIT -1 OFFSET ?`,
)
.all(doc.id, MAX_VERSIONS_PER_DOCUMENT);
if (excess.length > 0) {
const placeholders = excess.map(() => '?').join(',');
db.prepare(`DELETE FROM document_versions WHERE id IN (${placeholders})`).run(
...excess.map((row) => row.id),
);
}
}
// Snapshot only when the latest version is older than the coalescing window
// (or when there is no version yet). Returns true when a snapshot was taken.
export function maybeSaveDocumentVersion(db, doc, createdAt) {
const latest = db
.prepare(
`SELECT created_at FROM document_versions
WHERE document_id = ?
ORDER BY created_at DESC
LIMIT 1`,
)
.get(doc.id);
if (latest) {
const age = Date.parse(createdAt) - Date.parse(latest.created_at);
if (age < VERSION_COALESCE_MS) {
return false;
}
}
saveDocumentVersion(db, doc, createdAt);
return true;
}
|