Roadmap¶
go-ruby-pstore/pstore is grown test-first, each capability differential-tested
against MRI rather than built in isolation. PStore's transaction engine — the
deterministic, interpreter-independent slice extracted from rbgo's internals — is
complete.
| Stage | What | Status |
|---|---|---|
| Transaction state machine | Transaction(readOnly, body) runs PStore's load → body → commit/abort machine over a Hash table, refusing a nested transaction and raising outside one. |
Done |
| Commit on normal exit | A read-write transaction whose body returns normally Marshal-dumps the table back through the backend — only if the bytes changed (MRI's checksum/size guard). | Done |
| Commit / Abort early exit | t.Commit() / t.Abort() from the body exit it early (MRI's throw :pstore_abort_transaction): Abort discards every change, Commit persists the work so far. |
Done |
| Read-only transactions & error taxonomy | In a read-only transaction Set / Delete raise PStore::Error and the backend is never written; a single *pstore.Error carries MRI's exact messages. |
Done |
| MRI-compatible on-disk Marshal | The table is Marshal.dump / loaded via go-ruby-marshal, so files round-trip both directions with MRI's PStore. |
Done |
| Differential oracle & coverage | Real ruby -rpstore files loaded here, the table round-tripped both directions, and MRI's commit / abort / read-only sequence replayed and asserted; 100% coverage, gofmt + go vet clean, green across all six 64-bit Go arches and three OSes. |
Done |
Documented out-of-scope boundaries¶
These are deliberate, recorded so the module's surface is unambiguous:
- The file/locking layer is the consumer's. Opening the store,
flock, and the atomic-rename / rewind-truncate save strategies are injected through a two-methodBackend. The host supplies the realos.File+syscall.Flock— that is whyrbgobinds this module rather than the reverse. - Reference is reference Ruby (MRI). Byte-for-byte on-disk compatibility targets
MRI's
PStore; differences across MRI releases are matched to the reference used by the differential oracle. - Standalone & reusable. The module has no dependency on the Ruby runtime; the dependency runs the other way.
See Usage & API for the surface and Why pure Go for the deterministic/file-seam split.