-- Abgleich nur der Aenderungen (RFC 6578, sync-collection). -- -- Bis hierher holte jeder Durchgang die **volle** Terminliste: Der Client -- fragt das ctag ab, sieht es veraendert und laedt alles neu. Bei einem Jahr -- Termine ist das jedes Mal dieselbe Menge Daten fuer eine Aenderung. -- -- Was dafuer fehlt, ist eine Reihenfolge: "was hat sich seit Stand N getan". -- Ein **zweiter** Zaehler waere dafuer nicht noetig -- das ctag ist bereits -- genau das: eine Zahl je Kalender, die bei jedem Schreiben um eins steigt. -- Sie wird deshalb hier zur Sync-Sequenz; jedes Objekt merkt sich den Stand, -- bei dem es zuletzt angefasst wurde. ALTER TABLE cal_objects ADD COLUMN IF NOT EXISTS sync_seq BIGINT NOT NULL DEFAULT 0; -- Bestehende Objekte auf den heutigen Stand ihres Kalenders setzen. Ein -- Client hat noch kein Token (die Eigenschaft gab es bis jetzt nicht), holt -- also ohnehin einmal alles und bekommt dabei sein erstes Token. UPDATE cal_objects o SET sync_seq = c.ctag FROM cal_calendars c WHERE c.id = o.calendar_id; CREATE INDEX IF NOT EXISTS cal_objects_sync ON cal_objects (calendar_id, sync_seq); -- Grabsteine: Eine geloeschte Zeile kann nicht mehr erzaehlen, dass es sie -- gab. Ohne sie bliebe ein geloeschter Termin auf jedem Geraet stehen, das -- waehrend des Loeschens nicht verbunden war -- der teuerste Fehler dieser -- Art, weil er unsichtbar ist. CREATE TABLE IF NOT EXISTS cal_tombstones ( calendar_id UUID NOT NULL REFERENCES cal_calendars(id) ON DELETE CASCADE, uid TEXT NOT NULL, sync_seq BIGINT NOT NULL, deleted_at TIMESTAMPTZ NOT NULL DEFAULT now(), PRIMARY KEY (calendar_id, uid) ); CREATE INDEX IF NOT EXISTS cal_tombstones_sync ON cal_tombstones (calendar_id, sync_seq); -- Bis zu diesem Stand sind Grabsteine weggeraeumt. Ein Client mit einem -- aelteren Token bekommt eine klare Absage () und macht -- einen Vollabgleich -- besser als eine Antwort, in der Loeschungen fehlen. ALTER TABLE cal_calendars ADD COLUMN IF NOT EXISTS sync_floor BIGINT NOT NULL DEFAULT 0;