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.
4.2 KiB
Datalaget
Status: Besluttet. Revidert mars 2026 — SpacetimeDB fjernet.
PostgreSQL er eneste datakilde. Sanntid via PG
LISTEN/NOTIFYog WebSocket i portvokteren. CAS lagrer binærdata. Apache AGE legges til ved behov for Cypher-traverseringer.
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:
tsvectorpånodes.contentognodes.title - Semantisk søk: pgvector for embedding-basert likhet
- Graftraversering: rekursive CTEs, Apache AGE ved behov
- Statistikk: aggregeringer, tidsserier
- Tilgangsmatrise:
node_accessberegnet 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:
- Nå: PG med nodes/edges-tabeller og CTEs
- Når CTEs blir smertefulle: Legg til AGE
- 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. 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
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
É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
- Noder er sentrum — tilgangsmatrise beregnet fra edge-grafen, brukes for WebSocket-filtrering
- Universell input og mottak — noder og edges er datamodellen for alle tre primitiver
- Maskinrommet / Portvokteren — CAS-pruning, edge-drevet ressursorkestrering, validering før skriving, WebSocket-endepunkt for sanntid