Documentation
¶
Overview ¶
Example 04_persistence — the full GoGraph durability path on a real directory, driven at a configurable, reproducible scale.
It builds a seeded software-supply-chain graph entirely through WAL-committed transactions, takes a v2 snapshot (CSR + labels.bin + properties.bin), drops every in-memory reference, then rebuilds the graph from disk with recovery.Open and verifies the data survived.
- Every mutation — nodes, labels, edges, edge labels, typed node properties, typed edge properties — is appended to the WAL and applied to the in-memory LPG inside a committed transaction, so the whole graph is durable, not just its topology.
- snapshot.WriteSnapshotFull persists the CSR view, labels.bin and properties.bin atomically alongside the WAL — a checkpoint of the label and typed-property state.
- The process "restarts": every in-memory reference is dropped and recovery.Open rebuilds the graph from the snapshot plus the WAL tail. The recovered graph is then queried back through the LPG read API to confirm counts and sample property values round-trip.
Model ¶
(:Package {name, language, downloads}) // a published library
(:Release {coord, version, published}) // one version of a package
(:Package)-[:PUBLISHED {weight}]->(:Release) // package owns its releases
(:Release)-[:DEPENDS_ON {constraint, weight}]->(:Package)
Every Package owns exactly one Release in this model (coord = name@version), and each Release declares a random number of DEPENDS_ON edges to other packages, each carrying a semver-style version constraint string and an int64 weight (the declared dependency rank). PUBLISHED and DEPENDS_ON edges both carry a durable int64 weight, so the WAL exercises OpAddEdgeWeighted and the typed-property path carries strings, int64s and a timestamp.
All node and edge properties are written inside the transaction, so they travel through the WAL (OpSetNodeProperty / OpSetEdgeProperty) and are replayed on recovery — the v2 snapshot's labels.bin / properties.bin is the checkpoint that lets recovery start from a compacted base rather than replaying the whole log.
Scale ¶
Run with no flags, the example builds a small, deterministic default (300 packages) that persists, snapshots and recovers well under a second, so `go test` stays comfortably inside the short-layer budget. Every dimension is a flag, so the same binary scales up to a size where the persistence cost is observable:
go run ./examples/04_persistence -packages 200000 -seed 7
The deterministic data shape — recovered node, edge and label counts and the sampled property values — is reproducible for a fixed -seed; only the telemetry (lines prefixed with "# ": throughput, on-disk bytes, recovery wall-clock and live heap) varies between runs and machines. The store is written to a directory created with os.MkdirTemp whose path differs every run and is deliberately never printed, so the report stays stable.