Technische Dokumentation

Zusammenfassung

Diese Dokumentation beschreibt interne technische Prozesse, die das Verständnis und den Umgang mit den Daten erleichtern, wenn mit diesen außerhalb der Receipts App umgegangen werden soll. Die Architektur ist im Geiste von “Local First” und “File Over App” entworfen.

Dateiformat - Sync

Log

Änderungen an Daten werden in ein spezielles fortlaufendes “Log” geschrieben. Dabei schreibt jede Installation ihren eigenen Log. Installationen werden durch eine unikale clientId unterschieden. Die Einträge in jedem Log werden fortlaufend mit ganzen Zahlen nummeriert, beginnend mit der 0. Im Dateisystem wird aus technischen Gründen (Vermeidung von Konflikten, Integritätsprüfung, Vereinfachung für fremde Datei-Sync-Services) für jeden Eintrag eine eigene Datei erzeugt, die nach einem Verteilungs-Algorithmus zu je 1000 Dateien in einzelne Verzeichnisse geschrieben werden.

Änderungen

Die Änderungen der lokalen Datenbank werden als Liste gesammelt und in einer Transaktion (transactions) zusammengefasst. Durch den Wert von _id wird jedes einzelne Datenbank-Objekt eindeutig identifiziert. Der ganzzahlige Wert von _v wird für die Last-Write-Wins (LWW) Methode verwendet (Lamport-Clock), um bei der Wiederherstellung einen letztendlich konsistenten Datenbestand sicherzustellen. Dabei werden nur die neuen Werte beim Sync gesetzt, deren _v Eintrag größer als der vorgefundene Wert ist. Sollte es dort zum Konflikt kommen, gewinnt der Eintrag mit dem höheren Zeitstempel. Durch diese Methode ist die Reihenfolge der Anwendung der Änderungseinträge unerheblich (CRDT).

Dateiformat

Die Ablage erfolgt in der einfachsten Form als JSONL Datei. Die erste Zeile ist der Header und alle nach dem Zeilenwechsel folgenden Daten, in ihrer tatsächlichen binären Representation, sind der Content.

Der Header enthält die Prüfelemente s mit der Größe an Bytes des Contents. c die SHA256 Checksumme des Contents als Base64 mit URL konformer Kodierung (- statt + und _ statt /) ohne Padding. t ist die Uhrzeit der Erstellung als Timestamp in Sekunden. v enthält die Versionsnummer des Formates, die aktuell 1 ist, aber so für Anpassungen vorbereitet ist. Beispiel:

{"s":1473,"v":1,"c":"QHqyEU4WJOFsnxitlmsXFmpCXV2kZCCctzvO50_3IgM","t":1732311704}

Es folgen die einzelnen Änderung pro Zeile als JSON Objekt, wie in JSONL definiert. Siehe oben. Beispiel:

{"_id":"47855a70de36449f821d40b45f8c170a","_type":"category","_v":1,"title":"Telekommunikation"}

Dateianhänge

Dateien werden außerhalb der Datenbank gespeichert als Assets (assets). Diese werden ebenfalls pro Client mit einem fortlaufenden Index gespeichert, analog zu den Transaktionen. Datenbankeinträge verweisen auf Assets mit einer speziellen URL, die folgende Daten enthält:

  1. cid: Die Client-ID.
  2. idx: Der Index innerhalb der Assets Ablage.

Metadaten werden nicht mit abgelegt, sondern sind Teil des Verweises, wodurch wiederum auch die Konsistenz der Daten geprüft werden kann. Weitere Informationen sind:

  1. checksum: SHA-256 als Base64 kodiert.
  2. size: Größe in Bytes.
  3. type: MIME Type.
  4. name: Dateiname.

Der Verweis zum Asset wird als URL kodiert:

asset:///cid/idx/name?t=type&s=size&d=checksum

Beispiel:

asset:///1EH7BEtuL9xOz5aTpEyI4K/466/unnamed?s=6284&t=application%2Fpdf&d=JAd0HmXcSIVVdYMmDBjfVZeTvAyXQ94GmjA6CwSwOYU

Spezielle Datentypen

  • Der Verweis zu einem anderen Datensatz wird durch die _id des Eintrages realisiert. Der Name der Eigenschaft entspricht in der Regel dem Typ des Zielobjektes: _type.
  • Datum ohne Uhrzeit wird durch einen Integer Wert mit dem Format YYYYMMDD realisiert. Der 1. Dezember 2024 wird also als 20241201 dargestellt.
  • Der Betrag wird als Fließkommazahl dargestellt z. B. 1.23.
  • Timestamps sind in der Regel Sekundengenau.

Beispiel

node.js Projekt das die Receipts Sync Datei ausliest, die Datenbank herstellt und alle Daten (JSON) und Assets in den Ordner export schreibt:

Download Export Sample