Pipeline-Architektur
Daten fließen durch drei Stufen: Databricks Unity Catalog → S3 → RDS PostgreSQL. Die API hat zur Laufzeit keine direkte Verbindung zu Databricks — sie liest ausschließlich aus RDS. Die zugrunde liegenden Databricks-Jobs heißenparquet_to_s3 und ingest_parquet_to_rds.
Trassets’ interne Dokumentation beschreibt diesen Sync als täglich laufend. Die
öffentliche API-Schicht in diesem Repository hat keinen eigenen, maschinell erzwungenen
Zeitplan, gegen den man das prüfen könnte — der Sync-Takt ist eine Eigenschaft der
vorgelagerten Pipeline, nicht etwas, das die API konfiguriert oder offenlegt. Gehe nicht
von einer Aktualität unterhalb eines Tages aus — prüfe stattdessen immer
last_sync_at
(siehe unten), statt anzunehmen, dass ein festes Intervall verstrichen ist.TRUNCATE + Reload-Semantik
Bei jedem Sync-Lauf wird jede Tabelle vollständig gelöscht und komplett neu geladen — es gibt kein inkrementelles Update auf Zeilenebene innerhalb der Tabelle. Das hat zwei direkte Konsequenzen für Integratoren:- Kein partieller Sync. Eine Tabelle wird entweder vollständig durch den neuesten Sync ersetzt, oder gar nicht berührt. Es gibt keinen Mechanismus, um “nur die Zeilen zu synchronisieren, die sich geändert haben” innerhalb einer einzelnen Tabelle —
GET /changes(unten) sagt dir, welche Tabellen sich geändert haben, nicht welche Zeilen. - Schema-Änderungen sind für kumulative Tabellen immer ein Breaking Change. Bei Tabellen, die über mehrere Reloads hinweg Historie ansammeln (zum Beispiel
contract_ends), kann eine Schema-Änderung nicht additiv angewendet werden — TRUNCATE + Reload ersetzt immer den gesamten Tabelleninhalt, es gibt also keine Möglichkeit, alte Zeilen in-place in eine neue Form zu migrieren. Jede Schema-Änderung an einer solchen Tabelle wird als Breaking Change behandelt, der eine neue API-Version erfordert, wobei sowohl die alte als auch die neue Tabellenform während eines Deprecation-Fensters parallel synchronisiert werden.
Wann last_sync_at gesetzt wird
Der Sync-Status wird pro (customer_id, table_name) in einer internen Statustabelle mit diesen Feldern erfasst: last_sync_at (nullable Timestamp), status (synced, pending oder error), row_count, primary_key_column und error_message.
last_sync_at wird nur gesetzt, wenn ein Sync für diese Tabelle erfolgreich abgeschlossen wird — es bleibt NULL, bis der erste erfolgreiche Sync stattfindet, und ein fehlgeschlagener Sync (status = 'error') treibt es nicht voran. Das bedeutet:
- Eine Tabelle mit
status = 'pending'oderstatus = 'error'erscheint niemals inGET /changes, unabhängig davon, wie kürzlich ein Sync versucht wurde. last_sync_atspiegelt den Abschluss auf Tabellenebene wider, nicht den Änderungszeitpunkt einer einzelnen Zeile innerhalb dieser Tabelle.
Was GET /changes tatsächlich prüft
GET /changes?since=<timestamp> liefert eine Tabelle nur zurück, wenn alle der folgenden Bedingungen erfüllt sind:
statusist exakt'synced'(kein anderer Statuswert)last_sync_atist nichtNULLlast_sync_at > since— ein strikter Größer-als-Vergleich, kein>=
ETag-Response-Header ist das Maximum von last_sync_at über alle synchronisierten Tabellen eines Kunden. Polling mit If-None-Match erlaubt dir daher, einen Request komplett zu überspringen, wenn seit deinem letzten Poll nichts synchronisiert wurde (siehe Delta Sync für das vollständige Polling-Muster).
Praktische Auswirkungen für deine Integration
- Poll
/changes, statt einen Zeitplan zu raten. Da es kein dokumentiertes, erzwungenes Sync-Intervall gibt, baue deine Integration so, dass sie auf das reagiert, was/changesmeldet, statt anzunehmen, dass Daten zu einer festen Tageszeit aktualisiert werden. - Eine geänderte Tabelle bedeutet “alles für diese Tabelle neu abrufen”, nicht “hier sind die Diffs”. Änderungserkennung auf Zeilenebene existiert noch nicht — wenn eine Tabelle in
/changeserscheint, ist der sicherste Weg ein vollständiger erneuter Abruf dieser Category oder dieses Raw-Endpunkts. - Behandle
last_sync_atals Aktualitätssignal, nicht als Änderungsprotokoll. Es sagt dir, dass die Tabelle zu diesem Zeitpunkt erfolgreich neu geladen wurde; es sagt dir nicht, welche Zeilen sich von der vorherigen Version unterscheiden.