From c6bd8d8556ebee910bb6afe7bdedb05fe81446ac Mon Sep 17 00:00:00 2001 From: John Doty Date: Mon, 22 Jul 2024 16:20:22 -0700 Subject: [PATCH] Start reconcile --- cry/cli.py | 32 ++++++++++++++++++++++++++++++++ cry/database.py | 31 ++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/cry/cli.py b/cry/cli.py index 6bb988b..9a93c30 100644 --- a/cry/cli.py +++ b/cry/cli.py @@ -248,3 +248,35 @@ def unsubscribe(url): @cli.command("serve") def serve(): web.serve() + + +@cli.command("reconcile") +def reconcile(): + local_db = database.Database.local() + local_version = local_db.get_property("version", 0) + for p in database.databases_directory().glob("*.db"): + if not p.is_file(): + continue + + try: + other_db = database.Database.from_file(p) + if local_db.origin == other_db.origin: + continue + + other_version = other_db.get_property("version", 0) + if other_version != local_version: + click.echo( + f"{other_db.origin}: Not reconciling version {other_version} against {local_version}" + ) + continue + + # TODO: GET CLOCK OF BOTH. + other_clock = other_db.get_clock() + reconciled_clock = local_db.get_reconcile_clock(other_db.origin) + if other_clock == reconciled_clock: + continue + + # TODO: RECONCILE FOR REALS + + except Exception as e: + click.echo(f"Error loading {p}: {e}") diff --git a/cry/database.py b/cry/database.py index 4e5a934..138a831 100644 --- a/cry/database.py +++ b/cry/database.py @@ -99,6 +99,12 @@ SCHEMA_STATEMENTS = [ UPDATE properties SET value=value + 1 WHERE name='clock'; END; """, + """ + CREATE TABLE reconcile_status ( + origin VARCHAR NOT NULL PRIMARY KEY, + clock INT NOT NULL + ); + """, ] @@ -129,8 +135,12 @@ def local_origin(path: pathlib.Path | None = None) -> str: return origin +def databases_directory() -> pathlib.Path: + return pathlib.Path.home() / "Dropbox" / "cry" + + def database_path(origin: str) -> pathlib.Path: - return pathlib.Path.home() / "Dropbox" / "cry" / f"{origin}.db" + return databases_directory() / f"{origin}.db" # TODO: Refactor into: @@ -141,13 +151,18 @@ class Database: db: sqlite3.Connection origin: str - def __init__(self, path: pathlib.Path | str, origin: str): + def __init__(self, path: pathlib.Path | str, origin: str, readonly: bool = False): + uri = False if not isinstance(path, str): path.parent.mkdir(parents=True, exist_ok=True) + path = f"file:{str(path)}" + uri = True + if readonly: + path = f"{path}?mode=ro" # Enable autocommit as a separate step so that I can enable foreign # keys cleanly. (Can't enable foreign keys in a transaction.) - db = sqlite3.Connection(str(path)) + db = sqlite3.connect(str(path), uri=uri) db.execute("PRAGMA foreign_keys = ON") db.autocommit = False @@ -165,6 +180,16 @@ class Database: db = Database(database_path(origin), origin) db.ensure_database_schema() + db.set_property("origin", origin) + return db + + @classmethod + def from_file(cls, path: pathlib.Path) -> "Database": + db = Database(path, "", readonly=True) + origin = db.get_property("origin") + if origin is None: + raise Exception("No origin!") + db.origin = str(origin) return db def get_property(self, prop: str, default=None) -> typing.Any: