feat(calendar): Abgleich nur der Aenderungen (sync-collection, RFC 6578)
Bis hierher holte jeder Durchgang die volle Terminliste: ctag abfragen, Aenderung sehen, alles neu laden. Eine verschobene Besprechung kostete damit so viel wie ein Neuanfang -- bei einem Jahr Termine, alle fuenfzehn Minuten, auf Akku und Datenvolumen des Telefons. Kein zweiter Zaehler: Das ctag **ist** bereits eine Zahl je Kalender, die bei jedem Schreiben um eins steigt. Jedes Objekt merkt sich in sync_seq den Stand, bei dem es zuletzt angefasst wurde (Migration 24). Grabsteine (cal_tombstones) halten geloeschte UIDs fest -- ohne sie bliebe ein geloeschter Termin auf jedem Geraet stehen, das gerade nicht verbunden war. Sie stehen 180 Tage; beim Raeumen wandert sync_floor mit, und ein Token darunter bekommt 403 <valid-sync-token/> statt einer Antwort mit fehlenden Loeschungen. go-webdav kennt fuer REPORT nur calendar-query und calendar-multiget, und weder sync-token noch supported-report-set. Beide gehen denselben Weg wie getctag und calendar-color. Ohne supported-report-set probiert DAVx5 sync-collection gar nicht erst aus. Zwei Fehler noch vor dem Ausliefern gefunden: * Die Anfuehrungszeichen am ETag standen **innerhalb** der Maskierung -- xml.EscapeText machte daraus ". Gueltig, aber genug Clients vergleichen ETags roh und saehen bei jedem Durchgang eine Aenderung. * pruneTombstones nahm die erste Zeile eines DELETE ... RETURNING als Maximum. Das hat keine Reihenfolge -- der sync_floor waere zu niedrig gesetzt worden, und ein Client dazwischen haette Loeschungen verpasst. caldav-selbsttest.py: 62 -> 86 Pruefungen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
df9d2d6ded
commit
8fdde182b7
11 files changed
+728
-33
No files matched your search
+47
-1
@@ -86,7 +86,7 @@ Die abgeleiteten Spalten sind nur zum Vorsortieren da.
|
||||
| **1** | CalDAV lesend und schreibend, ein Kalender, Anmeldung über App-Passwörter, Auffindpfade (`/.well-known/caldav`, `current-user-principal`, `calendar-home-set`). Ziel: DAVx5 gleicht ab. | ✅ |
|
||||
| **2** | Mehrere Kalender, Farbe, Umbenennen, Löschen. Export als `.ics`, Import einer bestehenden Datei. | ✅ |
|
||||
| **3** | Weboberfläche in Aether: Monat, Woche, Liste; Termin anlegen, ändern, löschen. Der Teil, der Spaß macht – und dessen Fehler man **sieht**. | ✅ |
|
||||
| **4** | `sync-collection` statt Vollabgleich, Aufgabenansicht, Teilen mit anderen Nutzern, öffentlicher Abo-Link, Kalender in der HoneyOS-Leiste. | offen |
|
||||
| **4** | `sync-collection` ✅, Aufgabenansicht, Teilen mit anderen Nutzern, öffentlicher Abo-Link, Kalender in der HoneyOS-Leiste. | läuft |
|
||||
| **5** | Kontakte (CardDAV). Dieselbe Maschinerie, dieselbe Bibliothek – und **einfacher**, weil es dort keine Wiederholungen gibt. | später entscheiden |
|
||||
|
||||
Über die Phasen hinaus dazugekommen, weil es sich beim Prüfen als nötig
|
||||
@@ -109,6 +109,52 @@ erwies:
|
||||
Wege führen auf dieselben Daten, aber über völlig verschiedenen Code – ein
|
||||
grüner Lauf des einen sagt nichts über den anderen.
|
||||
|
||||
## Abgleich nur der Änderungen (Phase 4, erledigt 12.09.2026)
|
||||
|
||||
Bis hierher lief jeder Durchgang so: Der Client fragt das `ctag` ab, sieht es
|
||||
verändert und holt daraufhin die **volle** Terminliste. Eine verschobene
|
||||
Besprechung kostet damit denselben Verkehr wie ein Neuanfang – bei einem Jahr
|
||||
Termine, jedes Mal, alle fünfzehn Minuten. Bezahlt wird das in Akku und
|
||||
Datenvolumen des Telefons.
|
||||
|
||||
`sync-collection` (RFC 6578) dreht das um: Der Client sagt „ich bin auf Stand
|
||||
41" und bekommt zurück, was seither geschah, plus ein neues Token.
|
||||
|
||||
**Kein zweiter Zähler.** Das `ctag` *ist* bereits eine Zahl je Kalender, die
|
||||
bei jedem Schreiben um eins steigt – also genau die Sequenz, die hier gebraucht
|
||||
wird. Jedes Objekt merkt sich in `sync_seq` den Stand, bei dem es zuletzt
|
||||
angefasst wurde. Ein eigener Sync-Zähler daneben wäre eine zweite Wahrheit über
|
||||
denselben Sachverhalt gewesen, und zwei Wahrheiten laufen auseinander.
|
||||
|
||||
**Grabsteine.** Eine gelöschte Zeile kann nicht mehr erzählen, dass es sie gab.
|
||||
`cal_tombstones` hält deshalb UID und Stand jedes gelöschten Termins fest –
|
||||
sonst bliebe er auf jedem Gerät stehen, das während des Löschens nicht
|
||||
verbunden war. Das ist der teuerste Fehler dieser Art, weil er unsichtbar ist.
|
||||
|
||||
Grabsteine stehen 180 Tage; beim Räumen wandert `sync_floor` mit. Ein Token
|
||||
darunter lässt sich nicht mehr vollständig beantworten, und dann ist die
|
||||
ehrliche Antwort `403 <valid-sync-token/>` – der Client gleicht daraufhin voll
|
||||
ab. Eine lückenhafte Antwort wäre schlimmer als eine Absage: Der Client hielte
|
||||
sie für den ganzen Unterschied.
|
||||
|
||||
Drei Feinheiten, die beim Bauen auffielen:
|
||||
|
||||
- **Beim ersten Abgleich keine Grabsteine.** Wer den Kalender noch gar nicht
|
||||
kennt, braucht keine Löschmeldungen für Termine, die er nie gesehen hat.
|
||||
- **Auferstehung.** Wird eine gelöschte UID neu angelegt, muss ihr Grabstein
|
||||
weg – sonst bekäme der Client die Datei und ihre Todesmeldung im selben Zug.
|
||||
- **Anführungszeichen am ETag stehen außerhalb der Maskierung.** `xml.EscapeText`
|
||||
macht daraus sonst `"`; gültiges XML, aber genug Clients vergleichen
|
||||
ETags als rohe Zeichenkette und sähen bei jedem Durchgang eine Änderung.
|
||||
|
||||
Dazu zwei Eigenschaften, die go-webdav gar nicht kennt und die jetzt denselben
|
||||
Weg gehen wie `getctag` und `calendar-color` (`propfind.go`): `sync-token` und
|
||||
`supported-report-set`. Ohne die zweite probiert DAVx5 `sync-collection` nicht
|
||||
einmal aus.
|
||||
|
||||
Geprüft in `scripts/caldav-selbsttest.py` (86 statt 62 Prüfungen), darunter der
|
||||
Fall, auf den es ankommt: *ohne Änderung kommt nichts zurück*.
|
||||
|
||||
## Teilen – drei Bedeutungen, zwei davon gehen
|
||||
|
||||
„Geteilter Kalender" meint je nach Person etwas anderes:
|
||||
|
||||
Reference in new issue
Block a user