Start reconcile
This commit is contained in:
parent
5a834d5d26
commit
c6bd8d8556
2 changed files with 60 additions and 3 deletions
32
cry/cli.py
32
cry/cli.py
|
|
@ -248,3 +248,35 @@ def unsubscribe(url):
|
||||||
@cli.command("serve")
|
@cli.command("serve")
|
||||||
def serve():
|
def serve():
|
||||||
web.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}")
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,12 @@ SCHEMA_STATEMENTS = [
|
||||||
UPDATE properties SET value=value + 1 WHERE name='clock';
|
UPDATE properties SET value=value + 1 WHERE name='clock';
|
||||||
END;
|
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
|
return origin
|
||||||
|
|
||||||
|
|
||||||
|
def databases_directory() -> pathlib.Path:
|
||||||
|
return pathlib.Path.home() / "Dropbox" / "cry"
|
||||||
|
|
||||||
|
|
||||||
def database_path(origin: str) -> pathlib.Path:
|
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:
|
# TODO: Refactor into:
|
||||||
|
|
@ -141,13 +151,18 @@ class Database:
|
||||||
db: sqlite3.Connection
|
db: sqlite3.Connection
|
||||||
origin: str
|
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):
|
if not isinstance(path, str):
|
||||||
path.parent.mkdir(parents=True, exist_ok=True)
|
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
|
# Enable autocommit as a separate step so that I can enable foreign
|
||||||
# keys cleanly. (Can't enable foreign keys in a transaction.)
|
# 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.execute("PRAGMA foreign_keys = ON")
|
||||||
db.autocommit = False
|
db.autocommit = False
|
||||||
|
|
||||||
|
|
@ -165,6 +180,16 @@ class Database:
|
||||||
|
|
||||||
db = Database(database_path(origin), origin)
|
db = Database(database_path(origin), origin)
|
||||||
db.ensure_database_schema()
|
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
|
return db
|
||||||
|
|
||||||
def get_property(self, prop: str, default=None) -> typing.Any:
|
def get_property(self, prop: str, default=None) -> typing.Any:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue