synops/docs/retninger/datalaget.md
vegard fd0b75ee13 Orkestrering: tre nivåer (script/fritekst/drøm) + rename portvokter→vaktmester
Orkestrering restrukturert med deklarativt script som primærnivå:
- Nivå 1: eksakte CLI-kall med {event.*}-variabler, ingen AI
- Nivå 2: fritekst tolket av bot med function calling
- Nivå 3: drømmemodus — bruker skriver fritt, mangler→work_items
- Auto-eskalering: script→bot ved uventet feil

Rename portvokter→vaktmester i alle docs — bedre navn for en
tjeneste som gjør ting, ikke bare sjekker legitimasjon.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 15:59:29 +00:00

4.2 KiB

Datalaget

Status: Besluttet. Revidert mars 2026 — SpacetimeDB fjernet.

PostgreSQL er eneste datakilde. Sanntid via PG LISTEN/NOTIFY og WebSocket i vaktmesteren. CAS lagrer binærdata. Apache AGE legges til ved behov for Cypher-traverseringer.

Lagmodell

GUI (SvelteKit)
  │ skriv                    │ les (sanntid, WebSocket)
  ▼                          ▼
Vaktmesteren (Rust)         Vaktmesteren ──WebSocket──→ GUI
  │ validering                 ▲
  └──→ PostgreSQL ──NOTIFY──→──┘

Skrivestien

GUI → vaktmesteren → validering → PG. Frontend oppdateres via WebSocket-push utløst av PG NOTIFY.

Lesestien (sanntid)

PG → vaktmesteren → WebSocket → GUI. Vaktmesteren holder en in-memory cache av aktive subscriptions og pusher relevante endringer til tilkoblede klienter.

Lesestien (tunge spørringer)

GUI → vaktmesteren → PG. Fulltekstsøk, pgvector, statistikk, AGE-traverseringer.

PostgreSQL — eneste datakilde

Én sannhetskilde. Ingen synk, ingen konsistensproblemer:

  • Sanntid: LISTEN/NOTIFY → vaktmesteren → WebSocket
  • Fulltekstsøk: tsvectornodes.content og nodes.title
  • Semantisk søk: pgvector for embedding-basert likhet
  • Graftraversering: rekursive CTEs, Apache AGE ved behov
  • Statistikk: aggregeringer, tidsserier
  • Tilgangsmatrise: node_access beregnet fra edges

Apache AGE — ved behov

De fleste spørringer er grunne (1-3 hopp) og håndteres av CTEs. AGE legges til som PG-extension når Cypher-semantikk faktisk trengs:

  1. Nå: PG med nodes/edges-tabeller og CTEs
  2. Når CTEs blir smertefulle: Legg til AGE
  3. Usannsynlig: Evaluer Neo4j hvis AGE ikke holder

AGE er en extension, ikke en migrering.

CAS — binærlagring

Lyd, bilde, video lagres content-addressable på disk. CAS-noder i grafen bærer metadata (cas_hash, mime, size_bytes). Selve biten lever utenfor PG.

Pruning-regler basert på modalitet, edges og aksessmønstre. Se maskinrommet.

Sanntid via PG LISTEN/NOTIFY

PG har innebygd pub/sub. Vaktmesteren lytter og videresender:

PG: NOTIFY node_changed, '{"id":"abc","kind":"content"}'
  → Vaktmesteren mottar
  → Sjekker tilgangsmatrise: hvem skal se denne endringen?
  → Pusher til relevante WebSocket-tilkoblinger
  → Frontend oppdaterer reaktivt

Trigger i PG

CREATE OR REPLACE FUNCTION notify_node_change()
RETURNS trigger AS $$
BEGIN
  PERFORM pg_notify('node_changed',
    json_build_object(
      'op', TG_OP,
      'id', NEW.id,
      'kind', NEW.node_kind
    )::text
  );
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER nodes_notify
  AFTER INSERT OR UPDATE ON nodes
  FOR EACH ROW EXECUTE FUNCTION notify_node_change();

Tilsvarende for edges.

WebSocket i vaktmesteren

Vaktmesteren holder:

  • Map av tilkoblede klienter → brukerens node_id
  • Map av node_id → synlige noder (fra node_access)
  • Ved NOTIFY: filtrer på tilgang, push til relevante klienter

Én retning (PG → klient), ingen reducer-logikk, ingen konsistensproblemer.

Historikk: SpacetimeDB (fjernet mars 2026)

SpacetimeDB ble brukt som sanntidslag i v1/prototype. Det løste sanntid elegant, men for produksjon på én server skapte det unødvendig kompleksitet:

  • Synk-kompleksitet. PG ↔ STDB synk var en egen feilkategori.
  • Dobbelt vedlikehold. STDB-modul med reducers måtte holdes i synk med PG-skjema.
  • Ekstra SPOF. Enda en tjeneste å overvåke og restarte.
  • Unødvendig for skalaen. PG LISTEN/NOTIFY + WebSocket gir ~5ms latency — umerkelig forskjell for brukere.

SpacetimeDB ble faset ut i fire steg: WebSocket-lag, frontend- migrering, fjern skrivestien, fjern alt. Se erfaringsdocs for lærdommer: docs/erfaringer/spacetimedb_integrasjon.md.

Forhold til andre retninger