Revider datalaget: fas ut SpacetimeDB, PG LISTEN/NOTIFY + WebSocket
SpacetimeDB var et godt eksperiment, men gir synk-kompleksitet, dobbelt vedlikehold og en ekstra SPOF for minimal latensgevinst på denne skalaen. PG LISTEN/NOTIFY + WebSocket i portvokteren erstatter sanntidslaget. - datalaget.md: revidert med ny lagmodell, PG-triggers, migrasjonsplan - retninger/README.md: oppdatert status til «Revidert» - tasks.md: ny fase 22 (STDB-migrering) med 5 oppgaver (M1–M5) - 12.4 oppdatert fra «profiler STDB» til «profiler PG» Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0f03886091
commit
81d2ece2f1
3 changed files with 130 additions and 48 deletions
|
|
@ -26,7 +26,7 @@ andre dokumenter. En retning kan også forkastes eller parkeres.
|
|||
| [Universell input og mottak](universell_input.md) | **Besluttet** | Én multimodal input-primitiv, én mottaksflate, kommunikasjonsnoder. Edges definerer alt. |
|
||||
| [Maskinrommet](maskinrommet.md) | **Besluttet** | Én Rust-tjeneste: fang, prosesser, lever. Eier all skriving. Edge-drevet ressursorkestrering. |
|
||||
| [Noder er sentrum](bruker_ikke_workspace.md) | **Besluttet** | Alt er noder (brukere, team, innhold). Edges definerer relasjoner og tilgang. Materialisert tilgangsmatrise for RLS. |
|
||||
| [Datalaget](datalaget.md) | **Besluttet** | SpacetimeDB holder hele grafen, PG er persistent arkiv, CAS for binærdata, AGE ved behov |
|
||||
| [Datalaget](datalaget.md) | **Revidert** | PG er eneste datakilde. Sanntid via LISTEN/NOTIFY + WebSocket. SpacetimeDB fases ut. CAS for binærdata, AGE ved behov. |
|
||||
| [Arbeidsflaten](arbeidsflaten.md) | **Besluttet** | Spatial canvas med verktøy-paneler. Drag-and-drop skaper nye noder med edges. |
|
||||
| [Unix-filosofi](unix_filosofi.md) | **Besluttet** | Maskinrommet orkestrerer, CLI-verktøy gjør jobben. Claude deler verktøykasse. |
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
# Datalaget
|
||||
|
||||
**Status: Besluttet.**
|
||||
**Status: Besluttet. Revidert mars 2026 — SpacetimeDB fases ut.**
|
||||
|
||||
> SpacetimeDB holder hele grafen i minne og mottar skrivinger først.
|
||||
> PostgreSQL er persistent arkiv og backup. CAS lagrer binærdata.
|
||||
> 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
|
||||
|
||||
|
|
@ -12,47 +13,34 @@
|
|||
GUI (SvelteKit)
|
||||
│ skriv │ les (sanntid, WebSocket)
|
||||
▼ ▼
|
||||
Maskinrommet (Rust) SpacetimeDB ──→ GUI
|
||||
Portvokteren (Rust) Portvokteren ──WebSocket──→ GUI
|
||||
│ validering ▲
|
||||
├──→ SpacetimeDB (først) ───┘
|
||||
└──→ PostgreSQL (asynk, persistent)
|
||||
└──→ PostgreSQL ──NOTIFY──→──┘
|
||||
```
|
||||
|
||||
### Skrivestien
|
||||
GUI → Maskinrommet → validering → SpacetimeDB (instant) → PG (asynk).
|
||||
Frontend oppdateres umiddelbart. PG persisterer i bakgrunnen.
|
||||
GUI → portvokteren → validering → PG. Frontend oppdateres via
|
||||
WebSocket-push utløst av PG NOTIFY.
|
||||
|
||||
### Lesestien (sanntid)
|
||||
SpacetimeDB → GUI (direkte WebSocket, ~10μs).
|
||||
Hele grafen er i SpacetimeDB. Frontend har alltid alt tilgjengelig.
|
||||
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 → Maskinrommet → PG.
|
||||
Fulltekstsøk, pgvector (semantisk søk), statistikk, AGE-traverseringer.
|
||||
GUI → portvokteren → PG.
|
||||
Fulltekstsøk, pgvector, statistikk, AGE-traverseringer.
|
||||
|
||||
## SpacetimeDB — hele grafen i minne
|
||||
## PostgreSQL — eneste datakilde
|
||||
|
||||
Node- og edge-skjemaet er minimalt (åtte kolonner hver). For en
|
||||
liten brukerbase er hele grafen triviell å holde i minne. Fordeler:
|
||||
Én sannhetskilde. Ingen synk, ingen konsistensproblemer:
|
||||
|
||||
- Ingen sync-logikk for å bestemme hva som er "aktivt"
|
||||
- Ingen henting fra PG når noen åpner noe gammelt
|
||||
- Frontend har alltid alt via WebSocket
|
||||
- Én lesekilde — ingen tvetydighet
|
||||
|
||||
Når dette blir problematisk (hundretusenvis av noder), innføres
|
||||
eviction. Det er en optimalisering, ikke en arkitekturendring.
|
||||
|
||||
## PostgreSQL — arkiv og kraftspørringer
|
||||
|
||||
PG er persistent backup for hele grafen, pluss hjemsted for
|
||||
tunge operasjoner SpacetimeDB ikke er laget for:
|
||||
|
||||
- **Fulltekstsøk** — `tsvector` på `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` beregnes her, speiles til STDB
|
||||
- **Sanntid:** `LISTEN/NOTIFY` → portvokteren → WebSocket
|
||||
- **Fulltekstsøk:** `tsvector` på `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
|
||||
|
||||
|
|
@ -63,8 +51,7 @@ AGE legges til som PG-extension når Cypher-semantikk faktisk trengs:
|
|||
2. **Når CTEs blir smertefulle:** Legg til AGE
|
||||
3. **Usannsynlig:** Evaluer Neo4j hvis AGE ikke holder
|
||||
|
||||
AGE er en extension, ikke en migrering — boltes på uten å endre
|
||||
eksisterende kode.
|
||||
AGE er en extension, ikke en migrering.
|
||||
|
||||
## CAS — binærlagring
|
||||
|
||||
|
|
@ -75,23 +62,105 @@ Selve biten lever utenfor PG.
|
|||
Pruning-regler basert på modalitet, edges og aksessmønstre.
|
||||
Se [maskinrommet](maskinrommet.md).
|
||||
|
||||
## SpacetimeDB som utbyttbar
|
||||
## Sanntid via PG LISTEN/NOTIFY
|
||||
|
||||
SpacetimeDB er en sanntidscache, ikke en avhengighet. Hvis den
|
||||
fjernes:
|
||||
PG har innebygd pub/sub. Portvokteren lytter og videresender:
|
||||
|
||||
- **Sanntid:** PG `LISTEN/NOTIFY` → SvelteKit SSE
|
||||
- **Skriving:** Maskinrommet → PG direkte
|
||||
- **Lesing:** Maskinrommet → PG → GUI
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
Trenger ikke implementeres, men arkitekturen skal aldri gjøre
|
||||
det umulig. Se [synkronisering](../infra/synkronisering.md).
|
||||
### 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
|
||||
Implementer LISTEN/NOTIFY-lytter og WebSocket-endepunkt i
|
||||
portvokteren. Legg til PG-triggers for nodes og edges.
|
||||
Frontend kobler til begge (STDB + nytt WS) i parallell.
|
||||
|
||||
### Fase M2: Frontend-migrering
|
||||
Endre frontend fra SpacetimeDB-klient til vanlig WebSocket.
|
||||
Erstatt STDB-stores med reaktive stores som lytter på
|
||||
portvokterens WebSocket. Verifiser at all sanntidsfunksjonalitet
|
||||
fungerer.
|
||||
|
||||
### 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, speiles til SpacetimeDB
|
||||
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](maskinrommet.md) — CAS-pruning, edge-drevet
|
||||
ressursorkestrering, validering før skriving
|
||||
- [Maskinrommet / Portvokteren](maskinrommet.md) — CAS-pruning,
|
||||
edge-drevet ressursorkestrering, validering før skriving,
|
||||
WebSocket-endepunkt for sanntid
|
||||
|
|
|
|||
15
tasks.md
15
tasks.md
|
|
@ -42,6 +42,7 @@ Fase 3 + 13 → Fase 19 (arbeidsflaten — spatial canvas)
|
|||
Fase 19 → Fase 20 (universell overføring + panelrework)
|
||||
Fase 2 → Fase 21 (CLI-verktøy — unix-filosofi)
|
||||
Alt → Fase 12 (herding)
|
||||
Fase 12 → Fase 22 (SpacetimeDB-migrering)
|
||||
```
|
||||
|
||||
Hvis en oppgave er `[?]` eller `[!]`, hoppes den over — og alle
|
||||
|
|
@ -269,4 +270,16 @@ kaller dem direkte. Samme verktøy, to brukere.
|
|||
- [x] 12.1 Observerbarhet: strukturert logging, metrikker (request latency, queue depth, AI cost).
|
||||
- [x] 12.2 Backup: PG-dump rutine, STDB → PG gjenoppbygging ved krasj.
|
||||
- [ ] 12.3 Feilhåndtering: retry med backoff i skrivestien, dead letter queue for feilede PG-skrivinger.
|
||||
- [ ] 12.4 Ytelse: profiler STDB-spørringer, optimaliser node_access-oppdatering.
|
||||
- [ ] 12.4 Ytelse: profiler PG-spørringer, optimaliser node_access-oppdatering.
|
||||
|
||||
## Fase 22: SpacetimeDB-migrering — PG LISTEN/NOTIFY
|
||||
|
||||
Ref: `docs/retninger/datalaget.md` (revidert mars 2026). Faser ut SpacetimeDB
|
||||
til fordel for PG LISTEN/NOTIFY + WebSocket i portvokteren. Én datakilde,
|
||||
ingen synk-kompleksitet.
|
||||
|
||||
- [ ] 22.1 WebSocket-lag i portvokteren: implementer PG LISTEN/NOTIFY-lytter og WebSocket-endepunkt. Legg til PG-triggers (`notify_node_change`, `notify_edge_change`) for nodes og edges. Frontend kobler til begge (STDB + nytt WS) i parallell for verifisering.
|
||||
- [ ] 22.2 Frontend-migrering: erstatt SpacetimeDB-klient med vanlig WebSocket til portvokteren. Erstatt STDB-stores med reaktive stores som lytter på WebSocket. Verifiser all sanntidsfunksjonalitet (chat, kanban, kalender, mixer, canvas).
|
||||
- [ ] 22.3 Fjern STDB-skrivestien: portvokteren slutter å skrive til SpacetimeDB. All skriving går kun til PG. NOTIFY-triggere er eneste push-mekanisme. Verifiser at ingenting avhenger av STDB-data.
|
||||
- [ ] 22.4 Fjern SpacetimeDB: stopp Docker-container, fjern STDB-modul, fjern STDB-klient fra portvokteren og frontend, fjern synkroniseringskode, oppdater docs og CLAUDE.md.
|
||||
- [ ] 22.5 Opprydding: arkiver STDB-relaterte erfaringsdocs, oppdater alle docs-referanser, fjern Docker-konfig for SpacetimeDB, fjern SpacetimeDB-loven fra feedback-memories.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue