3 Commits

Author SHA1 Message Date
altair823
4898e13308 feat(backup): runDaily() with .last-snapshot marker + rotate after snapshot
Skips when marker matches today's KST date. Marker written after
successful snapshot, before rotation. lastSnapshotAt() exposed for UI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 03:08:30 +09:00
altair823
a728434b2e fix(backup): cleanup orphan .tmp on db.backup() failure + concurrency note
Code review I1: wrap snapshot's backup+rename in try/catch, unlink
orphan tmp file on failure so the next run does not encounter a
confusing 'existing file is not a database' error from sqlite.

Code review I2: JSDoc note that snapshot() is not safe for concurrent
calls — callers should serialize via runDaily()'s marker.

New unit test injects a fake db whose backup() rejects after a partial
write, asserts no .tmp / .sqlite remains.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 02:49:01 +09:00
altair823
714dd3fc9f feat(backup): atomic SQLite snapshot to inkling-YYYY-MM-DD.sqlite
KST date filename, tmp+rename atomic write, mkdir on demand.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 02:44:28 +09:00