From 581f33f72e20fe2fd7e9f6068cba96d377e7e1b3 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 24 Oct 2026 13:19:23 +0000 Subject: [PATCH] docs: keep an in-use SQLite database out of sync folders #94 catches a database file replaced during a write. Sync clients can also overwrite the file in place, upload it half-written, or fork it into conflicted copies, and nothing inside DID can see those. Add a "Where to keep the database file" section to docs/sqlitedb.md: - what each of those does; - what DID does and doesn't catch; - how to share or back up a database safely (close it, then copy the .sqlite file and its files/ directory together). Point to it from the SQLiteDB docstring. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012Dn4gCNCU2jUGdmfPVCAGK --- docs/sqlitedb.md | 27 ++++++++++++++++++++++++++- src/did/implementations/sqlitedb.py | 8 ++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/docs/sqlitedb.md b/docs/sqlitedb.md index 4be8a88..d9fabea 100644 --- a/docs/sqlitedb.md +++ b/docs/sqlitedb.md @@ -20,4 +20,29 @@ If the database file does not exist, it will be created automatically. ### Methods -The `SQLiteDB` class implements all of the abstract methods of the `Database` class, as well as the public methods for interacting with the database. \ No newline at end of file +The `SQLiteDB` class implements all of the abstract methods of the `Database` class, as well as the public methods for interacting with the database. + +### Where to keep the database file + +Keep a database that is in use **outside** folders that a sync or backup client +manages, such as Dropbox, OneDrive, iCloud Drive or Google Drive. The `files/` +directory next to it, where ingested files are stored, needs the same care. + +SQLite works through the file it opened, not through its name, and sync +clients change files behind its back. DID catches one of the ways they do it; +it cannot see the others: + +- **Replacing the file** with a downloaded version. DID detects this, both + before a write starts and just before it commits, and replays the write + against the new file. A replacement in the instant between that last check + and the commit is not caught. +- **Overwriting the file in place**, or uploading it half-written while a + write is under way. The other copy then holds a damaged or out-of-date + database. +- **Conflicted copies.** When two machines change the same database, the client + keeps both as separate files, and the changes in one never reach the other. + +To share a database or keep a backup, close it first (`db.close()`, in every +process that has it open), then copy the `.sqlite` file and its `files/` +directory together. Copy them to a synced folder if you like. Just don't open +a database from there while the client is running. diff --git a/src/did/implementations/sqlitedb.py b/src/did/implementations/sqlitedb.py index 0122b31..fdc3189 100644 --- a/src/did/implementations/sqlitedb.py +++ b/src/did/implementations/sqlitedb.py @@ -219,6 +219,14 @@ def __init__(self, document_obj, filename): class SQLiteDB(Database): + """A DID database in a SQLite file, with ingested files in ``files/``. + + Keep a database that is in use out of folders a sync client manages + (Dropbox, OneDrive, iCloud Drive, Google Drive): such clients replace, + overwrite or fork the file under an open connection. See "Where to keep + the database file" in docs/sqlitedb.md. + """ + def __init__(self, filename): super().__init__(connection=filename) self.dbid = None