factstr
factstr is the shared Rust contract crate for FACTSTR.
FACTSTR is an event store built around append-only facts, global sequencing, streams, durable streams, and command context consistency.
This crate defines the public contract and the core types. It does not store events by itself. Runtime stores live in separate crates.
What this crate provides
The factstr crate defines the common API used by all FACTSTR store implementations.
It includes:
- event input and event record types
- event queries and filters
- append results
- query results
- conditional append conflicts
- live stream contracts
- durable stream contracts
- the
EventStoretrait
The purpose of this crate is to keep the observable behavior of different stores aligned. Memory, SQLite, and PostgreSQL can use different internal mechanisms, but they implement the same public contract.
Store crates
Use this crate together with one of the runtime store implementations:
factstr-memoryfor tests, examples, and local developmentfactstr-sqlitefor embedded persistent usage without a separate database serverfactstr-postgresfor PostgreSQL-backed persistence
The core crate stays independent of those implementations.
Core idea
FACTSTR treats events as facts in one append-only log.
Each committed event receives a global sequence number. A committed batch receives one consecutive sequence range. Reads return events in ascending sequence order.
Consistency is checked against the facts relevant to a command. A command reads the current version of its context, then appends new facts only if that context has not changed.
That means consistency is not tied to aggregate roots or stream-per-entity ownership. The relevant context is described by an EventQuery.
Main operations
The shared contract supports:
appendqueryappend_ifstream_allstream_tostream_all_durablestream_to_durable
Important semantics
FACTSTR keeps several meanings explicit because they matter for correctness.
Append
Appending a batch produces an AppendResult with:
first_sequence_numberlast_sequence_numbercommitted_count
A successful batch is committed as one consecutive range.
Query
A query returns matching event records and two separate sequence meanings:
last_returned_sequence_numbercurrent_context_version
last_returned_sequence_number describes the events returned by the read.
current_context_version describes the full matching context used for consistency checks.
Those values are intentionally separate.
min_sequence_number
min_sequence_number is a read cursor only.
It limits which rows are returned by a query, but it does not shrink the consistency context used by append_if.
Conditional append
append_if appends only when the expected context version still matches the current version of the full matching context.
If the context changed, the store returns a conditional append conflict instead of appending a partial batch.
Streams
Live streams observe future committed batches.
Durable streams replay committed batches after a stored cursor and then continue with future delivery. Durable cursors must not advance past undelivered committed facts.
Contract types
The central public types are:
NewEventEventRecordEventFilterEventQueryQueryResultAppendResultDurableStreamEventStreamEventStoreEventStoreError
Example: query and conditional append
This example uses the contract shape. A concrete store such as factstr-memory or factstr-sqlite provides the actual implementation.
use ;
let context = reservation_context;
let event = NewEvent ;
The command first queries the context, reads current_context_version, and then calls append_if on a concrete store implementation.
Choosing a store
Use factstr-memory when the process lifetime is enough and persistence is not needed.
Use factstr-sqlite when the application should keep facts locally without operating a separate database server.
Use factstr-postgres when the application should use PostgreSQL as the persistent store.
Related packages
Rust store crates:
factstr-memoryfactstr-sqlitefactstr-postgres
Node and TypeScript package:
@factstr/factstr-node
License
Licensed under either of:
- MIT
- Apache-2.0