synops/docs/retninger/datalaget.md
vegard 8e80102f6b Fullfør oppgave 22.2: Frontend-migrering fra SpacetimeDB til portvokteren
Frontend bruker nå kun portvokterens WebSocket for sanntidsdata.
SpacetimeDB-klienten er erstattet med en enkel WebSocket-klient
som kobler til /ws-endepunktet og oppdaterer reactive stores direkte.

Frontend-endringer:
- Nye lokale typer (types.ts) erstatter STDB module_bindings
- connection.svelte.ts: WebSocket til portvokteren med auto-reconnect
- stores.svelte.ts: Prosesserer WS-meldinger (initial_sync + events)
- MixerTrait: STDB-reducers erstattet med HTTP API-kall
- api.ts: Nye mixer-endepunkter (create, gain, mute, effect, role)
- +layout.svelte: Fjernet dual-tilkobling, kun portvokterens WS
- pg-ws.svelte.ts: Slettet (erstattet av connection.svelte.ts)

Dokumentasjon:
- datalaget.md: Fase M1+M2 markert som fullført
- api_grensesnitt.md: Oppdatert arkitekturdiagram, nye mixer-endepunkter
2026-03-18 12:26:33 +00:00

168 lines
5.5 KiB
Markdown

# Datalaget
**Status: Besluttet. Revidert mars 2026 — SpacetimeDB fases ut.**
> PostgreSQL er eneste datakilde. Sanntid via PG `LISTEN/NOTIFY`
> og WebSocket i portvokteren. CAS lagrer binærdata.
> Apache AGE legges til ved behov for Cypher-traverseringer.
> SpacetimeDB fases ut — se migrasjonsplan.
## Lagmodell
```
GUI (SvelteKit)
│ skriv │ les (sanntid, WebSocket)
▼ ▼
Portvokteren (Rust) Portvokteren ──WebSocket──→ GUI
│ validering ▲
└──→ PostgreSQL ──NOTIFY──→──┘
```
### Skrivestien
GUI → portvokteren → validering → PG. Frontend oppdateres via
WebSocket-push utløst av PG NOTIFY.
### Lesestien (sanntid)
PG → portvokteren → WebSocket → GUI.
Portvokteren holder en in-memory cache av aktive subscriptions
og pusher relevante endringer til tilkoblede klienter.
### Lesestien (tunge spørringer)
GUI → portvokteren → PG.
Fulltekstsøk, pgvector, statistikk, AGE-traverseringer.
## PostgreSQL — eneste datakilde
Én sannhetskilde. Ingen synk, ingen konsistensproblemer:
- **Sanntid:** `LISTEN/NOTIFY` → portvokteren → WebSocket
- **Fulltekstsøk:** `tsvector``nodes.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](maskinrommet.md).
## Sanntid via PG LISTEN/NOTIFY
PG har innebygd pub/sub. Portvokteren lytter og videresender:
```
PG: NOTIFY node_changed, '{"id":"abc","kind":"content"}'
→ Portvokteren mottar
→ Sjekker tilgangsmatrise: hvem skal se denne endringen?
→ Pusher til relevante WebSocket-tilkoblinger
→ Frontend oppdaterer reaktivt
```
### Trigger i PG
```sql
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 portvokteren
Portvokteren 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
Enklere enn STDB-synk: én retning (PG → klient), ingen
reducer-logikk, ingen konsistensproblemer.
## Hvorfor SpacetimeDB fases ut
SpacetimeDB var et godt eksperiment. Det løste sanntid elegant
i prototype-fasen. Men for produksjon på én server:
- **Synk-kompleksitet.** PG ↔ STDB synk er en egen feilkategori.
Erfaringsdocs (adapter_moenster.md, spacetimedb_integrasjon.md)
dokumenterer smerten.
- **Dobbelt vedlikehold.** STDB-modul med reducers må holdes i
synk med PG-skjema. Endring i nodes-tabellen → to steder.
- **Ekstra SPOF.** Enda en tjeneste å overvåke, restarte, debugge.
- **Unødvendig for skalaen.** PG LISTEN/NOTIFY + WebSocket gir
~5ms latency. STDB ga ~0.01ms. Forskjellen er umerkelig for
brukere.
- **CLI-verktøy forenkles.** Bare PG-tilkobling, ingen STDB-klient.
## Migrasjonsplan: STDB → PG LISTEN/NOTIFY
### Fase M1: WebSocket-lag i portvokteren ✅
Implementert LISTEN/NOTIFY-lytter og WebSocket-endepunkt i
portvokteren. PG-triggers for nodes, edges og access.
Frontend koblet til begge (STDB + nytt WS) i parallell.
### Fase M2: Frontend-migrering ✅
Frontend bruker nå kun portvokterens WebSocket. SpacetimeDB-klient
fjernet. Reactive stores oppdateres direkte fra WS-meldinger.
Berikede events: portvokteren henter full raddata fra PG etter
NOTIFY (ikke bare ID) slik at stores kan oppdateres uten ekstra
API-kall. Mixer-kanaler migrert fra STDB til PG-tabell med
tilhørende NOTIFY-trigger og HTTP API-endepunkter.
### Fase M3: Fjern skrivestien til STDB
Portvokteren slutter å skrive til SpacetimeDB. All skriving
går kun til PG. NOTIFY-triggere er eneste push-mekanisme.
### Fase M4: Fjern STDB
- Stopp SpacetimeDB Docker-container
- Fjern STDB-modul (spacetimedb/)
- Fjern STDB-klient fra portvokteren
- Fjern STDB-avhengigheter fra frontend
- Fjern synkroniserings-kode
- Oppdater docs (synkronisering.md → arkiver)
- Oppdater CLAUDE.md
### Fase M5: Opprydding
- Slett erfaringsdocs som kun gjelder STDB
- Oppdater alle docs-referanser til STDB
- Fjern Docker-konfig for SpacetimeDB
## Forhold til andre retninger
- [Noder er sentrum](bruker_ikke_workspace.md) — tilgangsmatrise
beregnet fra edge-grafen, brukes for WebSocket-filtrering
- [Universell input og mottak](universell_input.md) — noder og edges
er datamodellen for alle tre primitiver
- [Maskinrommet / Portvokteren](maskinrommet.md) — CAS-pruning,
edge-drevet ressursorkestrering, validering før skriving,
WebSocket-endepunkt for sanntid