Konnektor-Lebenszyklus
Die sechs Konnektor-Operationen — Handshake, Heartbeat, Full-Sync, Delta-Sync, Delete, Diagnose — und wie sie auf die Connector-API-Oberfläche abgebildet werden.
Ein CMS-Konnektor (PrestaShop, Bitrix, WordPress, Shopify) spricht mit AACsearch nur
über die Connector-API, die unter /api/connectors/** und
/api/projects/:projectId/** montiert ist. Er fasst Typesense nie direkt an. Jeder
Aufruf wird durch ein ss_connector_*-Token mit dem Scope connector_write gegated.
Lebenszyklus
Beschreibung
Das Diagramm durchläuft die sechs CMS-Connector-Phasen — Handshake, Heartbeat, Full-Sync, Delta-Sync, Delete, Diagnostics — jede gegated durch ein ss_connector_*-Token. Sync-Aufrufe erzeugen eine SearchConnectorSyncJob-Zeile plus N SearchSyncOutbox-Zeilen; der Worker leert das Outbox in den Typesense-Alias, während das CMS-Modul die jobId auf Fertigstellung pollt.
sequenceDiagram
autonumber
participant Mod as CMS module (PrestaShop / Bitrix / WP / Shopify)
participant API as packages/api/modules/search/connector-public.ts
participant Auth as gateConnectorRequest (scope=connector_write)
participant DB as PostgreSQL (SearchConnectorSyncJob + SearchSyncOutbox)
participant W as Sync worker
participant TS as Typesense alias
rect rgb(220, 252, 231)
note over Mod,API: Phase 1 — handshake (once per install)
Mod->>API: POST /api/connectors/handshake { moduleVersion, platform }
API->>Auth: verify ss_connector_* + connector_write
API-->>Mod: { projectId, indexSlug, capabilities, syncModes }
end
rect rgb(219, 234, 254)
note over Mod,API: Phase 2 — heartbeat (periodic, every ~5 min)
Mod->>API: POST /api/connectors/:connectorId/heartbeat
API-->>Mod: { status: "ok", timestamp }
end
rect rgb(254, 243, 199)
note over Mod,DB: Phase 3 — full sync (initial / on-demand)
Mod->>API: POST /api/projects/:projectId/sync/full { products[1..1000] }
API->>DB: createSyncJob(type=full)
API->>DB: executeSyncJob -> enqueue doc_upsert per product (outbox)
API-->>Mod: { jobId, total, queued }
W->>DB: drain outbox doc_upsert rows
W->>TS: bulkUpsert(batch, action=upsert)
W->>DB: completeSyncJob(jobId)
end
rect rgb(245, 243, 255)
note over Mod,DB: Phase 4 — delta sync (per change webhook)
Mod->>API: POST /api/projects/:projectId/sync/delta { products[1..100] }
API->>DB: createSyncJob(type=delta)
API->>DB: executeSyncJob -> outbox rows
API-->>Mod: { jobId, total, queued }
W->>TS: bulkUpsert(batch)
end
rect rgb(254, 226, 226)
note over Mod,TS: Phase 5 — delete (single or batch)
Mod->>API: DELETE /api/projects/:projectId/products/:externalId
API->>DB: enqueue doc_delete
W->>TS: delete_by_query(externalId)
Mod->>API: DELETE /api/connector/documents { externalIds[1..500] }
API->>DB: enqueue doc_delete (batch)
W->>TS: batch delete
end
rect rgb(241, 245, 249)
note over Mod,DB: Phase 6 — diagnostics (on demand / on error)
Mod->>API: POST /api/projects/:projectId/diagnostics { moduleVersion, lastFullSync, errors[] }
API->>DB: recordDiagnostics() (in-memory store + log)
API-->>Mod: { received: true }
endDie sechs Operationen
| Phase | HTTP | Body-Cap | Zweck | Persistiert |
|---|---|---|---|---|
| Handshake | POST /api/connectors/handshake | klein | Token bestätigen, Capabilities + Sync-Modi austauschen | Aktualisiert lastUsedAt |
| Heartbeat | POST /api/connectors/:connectorId/heartbeat | keiner | Modul-Lebens-Ping, Server-Zeit-Austausch | Aktualisiert lastUsedAt |
| Full-Sync | POST /api/projects/:projectId/sync/full | 1000 | Erstlast oder Reset; Bulk-Upsert des ganzen Katalogs | SearchConnectorSyncJob + Outbox-Zeilen |
| Delta-Sync | POST /api/projects/:projectId/sync/delta | 100 | Per-Change-Webhook aus dem CMS | SearchConnectorSyncJob + Outbox-Zeilen |
| Delete | DELETE /api/projects/:projectId/products/:externalIdDELETE /api/connector/documents | 1 / 500 | Ein Produkt / Batch entfernen | doc_delete-Outbox-Zeile(n) |
| Diagnose | POST /api/projects/:projectId/diagnostics | 4 KB | Selbstreport: PHP-Version, letzter Sync, Error-Log | In-Memory-Diagnostik-Store + strukturiertes Log |
Was jeden Aufruf gated
gateConnectorRequest läuft vor jeder Handler-Logik:
- Authorization-Header muss
Bearer ss_connector_*tragen. verifySearchApiKey(rawKey, "connector_write")— Admin-Scope ist eine Übermenge.- Liefert
{ keyId, organizationId, indexId, indexSlug }an den Handler. - Sync-Handler prüfen zusätzlich, dass
:projectIdmitorganizationIdübereinstimmt — sonst 404, falls ein Token gegen ein anderes Projekt verwendet wird.
Warum Job + Outbox
Die Connector-API blockiert nie auf Typesense. executeSyncJob schreibt eine
SearchConnectorSyncJob-Zeile für End-to-End-Sichtbarkeit plus N Zeilen in
SearchSyncOutbox, die der Worker drainiert. Das CMS-Modul erhält eine jobId, die es
zum Pollen verwenden kann; der Worker versöhnt jede Zeile unabhängig, sodass eine
einzelne fehlerhafte SKU den Batch nicht bricht.
Verwandt
- Schreibpfad — die Worker-Seite der Outbox.
- Schlüsseltypen & Sicherheitsmodell —
Form und Scope-Regeln des
ss_connector_*-Tokens.
Schlüsseltypen & Sicherheitsmodell
Die vier AACsearch-Schlüsselkategorien — search, connector, scoped und admin — ihre ss_*-Präfixe, ausschließlich gehashte Speicherung, Scoped-Token HMAC + TTL + Filter und wie sie zur Request-Zeit verifiziert werden.
Analyse-Feedback-Loop
Wie eine Suchanfrage zu einem SearchUsageEvent wird, wie Klicks und Conversions aufgezeichnet werden und wie die Aggregation das Dashboard für das Relevanz-Tuning speist.