synops/docs/infra/synkronisering.md
vegard b5aa5bb243 Fjern SpacetimeDB komplett (oppgave 22.4)
SpacetimeDB er nå helt fjernet fra Synops. Sanntid håndteres av
PG LISTEN/NOTIFY + WebSocket i portvokteren (maskinrommet).

Kode fjernet:
- spacetimedb/ Rust-modul og spacetime.json
- maskinrommet/src/stdb.rs (HTTP-klient for STDB-reducers)
- frontend module_bindings/ (23 auto-genererte filer)
- spacetimedb npm-avhengighet fra package.json
- scripts/test-sanntid.sh (testet STDB-flyt)

Infrastruktur:
- Docker-container stoppet og fjernet fra docker-compose.yml
- Caddy: fjernet /spacetime/* reverse proxy
- maskinrommet-env.sh: fjernet STDB_IP og SPACETIMEDB_*-variabler
- .env.example: fjernet SpacetimeDB-seksjoner

Dokumentasjon oppdatert:
- CLAUDE.md: stack, lagmodell, kjerneprinsipper, driftsmodell
- docs/arkitektur.md: skrivestien, lesestien, datalag, teknologivalg
- docs/retninger/datalaget.md: migrasjonshistorikk, status "fjernet"
- 37 andre docs oppdatert (features, concepts, infra, ops, retninger)
- Alle kode-kommentarer med STDB-referanser oppdatert

Verifisert: maskinrommet bygger og starter OK, frontend bygger OK,
helsesjekk returnerer 200. Caddy reloadet.
2026-03-18 13:39:09 +00:00

3.9 KiB

Synkronisering: SpacetimeDB ↔ PostgreSQL

UTGÅTT (mars 2026). SpacetimeDB er fjernet fra prosjektet. Sanntid leveres nå via PG LISTEN/NOTIFY + WebSocket i portvokteren. Se docs/infra/api_grensesnitt.md for gjeldende arkitektur. Dokumentet beholdes som historisk referanse.

Konsept

SpacetimeDB holder hele grafen (alle noder og edges) i minne. PostgreSQL er persistent backup og arkiv. Skriving går til begge. Lesing går fra SpacetimeDB.

GUI (SvelteKit)
  │ skriv                    │ les (sanntid)
  ▼                          ▼
Maskinrommet (Rust)          SpacetimeDB ──→ GUI
  │                            ▲
  ├──→ PostgreSQL (persistent) │
  └──→ SpacetimeDB ───────────┘

Hvorfor hele grafen i SpacetimeDB

Node- og edge-skjemaet er minimalt: åtte kolonner på nodes, åtte på edges. For en liten brukerbase er hele grafen triviell å holde i minne. Dette forenkler alt:

  • Ingen sync-logikk for å bestemme hva som er "aktivt"
  • Ingen henting fra PG når noen åpner noe gammelt
  • Frontend har alltid alt tilgjengelig via WebSocket
  • Én lesekilde — ingen tvetydighet

Når dette blir problematisk (hundretusenvis av noder, minnepress), innføres eviction basert på aksessmønstre. Men det er en optimaliseringsbeslutning, ikke en arkitekturbeslutning. Modellen endres ikke.

Skrivestien

Maskinrommet validerer, så skriver i to steg:

  1. Validering — tilgangssjekk, unique-constraints, forretningsregler
  2. SpacetimeDB først — frontend oppdateres umiddelbart (~10μs)
  3. PG asynkront — persistent backup i bakgrunnen

Frontend er allerede oppdatert mens PG-skrivingen skjer. Brukeren merker ingenting.

Hvis PG-skrivingen feiler: maskinrommet logger og prøver igjen. SpacetimeDB har dataen — den er bare ikke persistert ennå. Ingen datatap så lenge SpacetimeDB kjører.

Lesestien

Frontend leser kun fra SpacetimeDB via WebSocket-subscriptions. Ingen PG-kall fra frontend for data som vises i sanntid.

Unntak: tunge spørringer som ikke passer sanntidslaget — statistikk, fulltekstsøk, pgvector-søk, AGE-traverseringer. Disse går GUI → Maskinrommet → PG.

Oppvarming (PG → SpacetimeDB)

Ved oppstart av SpacetimeDB laster maskinrommet hele grafen fra PG:

  1. Alle noder
  2. Alle edges
  3. node_access-matrisen

Rekkefølge: noder først (edges refererer til noder). CAS-noder lastes uten binærinnhold (bare metadata).

Feilhåndtering

Scenario Konsekvens Håndtering
SpacetimeDB krasjer Sanntid forsvinner, upersistert data kan tapes Restart + oppvarming fra PG. Tap begrenset til skrivinger som ikke rakk PG.
PG nede Persistering stopper SpacetimeDB serverer lesing og mottar skrivinger. PG-backlog tas igjen ved recovery.
Maskinrommet krasjer Ingen skriving Frontend ser siste state. Restart plukker opp.

SpacetimeDB som utbyttbar

SpacetimeDB er en sanntidscache, ikke en avhengighet. Hvis den fjernes fra stacken:

  • Sanntid: PG LISTEN/NOTIFY → SvelteKit SSE
  • Skriving: Maskinrommet → PG direkte
  • Lesing: Maskinrommet → PG → GUI

Denne fallbacken trenger ikke implementeres, men arkitekturen skal aldri gjøre den umulig.

Tilgangsmatrise i SpacetimeDB

node_access-matrisen lastes inn i SpacetimeDB ved oppvarming. Når maskinrommet oppdaterer matrisen i PG (ved edge-endring), oppdaterer den også SpacetimeDB. SpacetimeDB-modulen bruker matrisen for å filtrere subscriptions — klienter ser kun noder de har tilgang til.

Konflikthåndtering

SpacetimeDB er single-threaded per modul — reducer-funksjoner serialiseres automatisk. Ingen klassiske race conditions.

Samtidig redigering (to brukere endrer samme node): maskinrommet serialiserer via SpacetimeDB. Last-write-wins. SpacetimeDB kringkaster resultatet til alle klienter. PG oppdateres asynkront med det endelige resultatet.