Track changes without an adapter#
The core needs no adapter and no protocol. Hand it everything a source holds, by id, and it works out what changed since the last run: what’s new, what changed, and what’s gone. The source can be anything you can read in full, such as a published calendar file, an export, or a table in another system.
import hashlib
import uuid
from calendaring_sync import Change, Changed, ChangeSet, MemoryStore, Replica, Unchanged
SCOPE = "team-calendar"
replica = Replica(MemoryStore())
def track(objects: dict[str, bytes]) -> None:
"""Hand the core everything the source holds now, by id."""
with replica.session(SCOPE, fingerprint_scheme="sha256", media_type="text/plain") as session:
since = replica.scope(SCOPE).token
known = replica.known_versions(SCOPE)
changes: dict[str, Change] = {}
for object_id, content in objects.items():
digest = hashlib.sha256(content).hexdigest()
if known.get(object_id) == digest:
changes[object_id] = Unchanged()
else:
changes[object_id] = Changed(digest, digest, content)
session.ingest(ChangeSet(SCOPE, since, uuid.uuid4().hex, changes, full_listing=True))
Each run is a full listing. The source has no version for each object, so the example uses the content’s hash as one. An object whose hash the store already holds is reported Unchanged, as known_versions() describes, and isn’t written again. An object the listing doesn’t mention is removed. The source has no sync token either, so each run gets a new one.
for _ in range(3):
track(read_source())
for entry in replica.read_feed():
print(entry.kind, entry.object_id)
The change feed reports each change once: both objects arriving, then the meeting moving and the lunch going. The second run found the source as it was and added nothing.
Keep the state between runs in a SQLite file, as Choose and set up a store shows, and read the feed from a cursor, as Read the change feed shows. To send edits back to the source too, write an adapter, as Write an adapter shows: the base classes hold the order of a two-way sync, so you write only how your source reads and writes.