Embedded in-memory engine¶
org.meridiandb.engine.InMemoryEngine implements the
initial numeric temporal contract in one
JVM. It supports ordered puts/retractions, historical point and interval queries,
exact aggregates, numeric predicates, explicit entity selection and request retries. It has no persistence: closing or crashing
loses values, history and request identity. The API is experimental, with no library
release or compatibility promise.
Run the example¶
Use JDK 25 and run from the repository root:
./mvnw -B verify
On Windows, verification uses .\mvnw.cmd -B verify. Then run the same Java command
on either platform:
java --class-path target/classes examples/EmbeddedExample.java
The example source opens an engine, records a salary, pins a view, applies a retroactive correction, and compares that view with a new one. Its output is:
February salary before correction: 100
February salary after correction: 120
Identical retry: commit 2, replayed=true
Coordinates are explicit epoch microseconds. The example uses numeric conformance values and does not define a salary schema, timestamp parser or public query language. Java CI runs the example after verification on Linux and Windows.
Entry points and lifetimes¶
| Entry point | Behavior |
|---|---|
new InMemoryEngine() |
Create an empty database with a fresh random lineage and genesis position 0 |
transact(Transaction) |
Serialize the validated ordered request; publish all changes together; return position/replay identity |
head() |
Capture the latest published database-local position |
openView(ReadCutoff.Head.INSTANCE) |
Pin the head once and return an independent ReadView |
openView(new ReadCutoff.At(position)) |
Select an existing cutoff in this engine's lineage |
lookupRequest(RequestId) |
Read current committed request metadata, independently of historical data views |
ReadView.position() / .query(TemporalQuery) |
Read the captured position and immutable point/scan/aggregate answers |
ReadView.close() |
Idempotently invalidate that view and release its snapshot reference |
InMemoryEngine.close() |
Idempotently close the engine and invalidate future operations on it and its views |
Use try-with-resources for both engines and views. Closing one view leaves the
engine and other views usable. After close, engine operations and affected view
position/query calls throw IllegalStateException. A query or view open that
already captured open state may finish while another thread closes it; close does
not cancel work already in progress. Writer commits and engine close serialize on
the same monitor, so no later writer publishes after engine close completes.
Foreign or future cutoffs raise EngineException with INVALID_CUTOFF; conflicting
reuse of a committed request ID raises REQUEST_ID_REUSED. New commits reject
sequence exhaustion with COMMIT_EXHAUSTED rather than wrapping. Invalid typed
arguments fail their constructors or required-argument checks. Request and result
records remain immutable; mutable caller lists cannot change a committed payload.
Publication and queries¶
The engine maintains sorted, nonoverlapping present-value intervals per entity. A writer copies the current value map, splits affected intervals around each operation, inserts a put or omits a retraction, then coalesces equal adjacent values. It preserves the immutable snapshot for every prior cutoff. Normalizing the finite minimum lower edge in stored state does not alter original request fields used for retry identity.
Writers serialize within one engine instance; simultaneous callers receive a total commit order without an arrival-order promise. A single volatile publication replaces a complete immutable state containing values, historical snapshots and request identities. Readers take a snapshot without acquiring the writer monitor. They cannot observe an operation in the middle of a transaction. An acknowledgement means that publication completed in memory. An identical retry returns its original position, even after later commits; a logical no-op with a new ID still commits.
Views can be shared by concurrent readers. Every operation in one view, including
all entities in an aggregate, uses its captured snapshot. New commits affect new
head views only. Point queries inspect the entity's intervals; scans clip existing
segments to the requested window; sums use exact BigInteger arithmetic.
Typed selection and filtered scans compare resolved present
values in the same snapshot, retain interval gaps and return immutable eager results. The
reference oracle instead searches transaction history and
partitions boundaries, providing a separate execution algorithm.
ADR 0006 records these choices and their alternatives. No backend or multi-process writer coordination exists here.
Verification and limits¶
./mvnw -B verify currently runs 747 JUnit test invocations, including the
71 temporal/engine checks below, 29 journal codec checks,
58 local journal I/O/process/prefix checks,
27 immutable segment codec checks,
36 local segment I/O/lifetime checks,
45 manifest codec/consistency checks,
39 local checkpoint publication checks,
37 local database recovery checks and
49 commit preparation/initialization/publication checks, plus
50 durable conformance checks and
55 typed query checks and
57 pure compaction checks and
55 local compaction publication/integration/process checks and
70 reader protection/identity/cleanup checks, and
69 reclamation inventory checks:
- The unchanged five canonical histories supply 84 expected steps for each of reference and engine, including invalid inputs and extreme coordinates.
- Sixteen persisted seeds supply 32 new transactions each, checked against forward dense snapshots as well as the reference. Every implementation receives 512 new transactions, plus retries/conflicts, with point, scan, aggregate and historical prefix comparisons.
- Nine focused engine tests cover fresh lineages/cutoffs, pinned views, close behavior, concurrent identical/conflicting retries, contiguous commits from distinct callers, atomic cross-entity reads and shared-view access.
- Type, interval boundary and strict fixture-decoding checks remain in the suite.
The concurrency checks coordinate bounded tasks with barriers and timed waits, without sleeps. They exercise real overlapping calls, but are not exhaustive JVM schedule exploration. The seed domain is deliberately small; this is correctness evidence, not a scale or performance claim. No failing semantic seed was found.
Run focused engine lifecycle/concurrency checks:
./mvnw -B -Dtest=InMemoryEngineTest test
The reference guide supplies fixture and seed reproduction commands and the failing-history preservation procedure.
This implementation retains every cutoff and request identity. It copies entity,
history and request maps on new commits and retains changed interval lists, so
memory use and write cost grow with history. It has no reclamation, index,
backpressure, crash recovery or benchmark claim. Sequence overflow is guarded;
practical memory capacity is reached long before the numeric sequence limit.
The journal codec implements the byte format;
the local adapter supplies append, force and sequential replay.
The separate local database shares interval-state and replay
logic. Private commit preparation creates all maps, request metadata and results
before storage I/O; publication checks the unchanged owner state, assigns one
immutable reference and returns the prepared result. InMemoryEngine.transact
uses the same split with no storage boundary and remains nonpersistent. The local
write path inserts append/force before publication. See
ADR 0014 for acknowledgement
and durability conformance for process exits and
canonical/seeded writable-reopen evidence.