Commit Database¶
The Commit Database provides transactional persistence with history tracking.
CommitDatabase is the persistence layer; two stateless namespaces operate
over it, each taking a CommitDatabase as its first argument:
CommitStateBuilder— reconstruct aCommitStatefrom a chosen commit:state(db, id),initial_state(db).CommitDatabaseHelper— reduce heads and navigate:reduce_heads(db, anchor),forward/fast_forward.
(CommitDatabase itself answers topology queries — head_commit_ids,
last_commit_id, is_ancestor — and holds no “current” state.) A
CommitStore wraps the persistence layer and both namespaces behind a
stateful facade (undo/redo, the dispatch surface) for interactive apps. For
why a reconstructed state is a blind replay of the linearized trace, see
Commit Database.
When to use: Use these classes to persist DSM documents with history —
every write is a commit, and earlier states stay reconstructible. For flat CRUD
without versioning, use Database instead. Within this page, reach for
CommitStore when an interactive application needs undo/redo and a dispatch
surface, and for the two stateless namespaces when a script or service drives
the database directly.
Quick Start¶
>>> from dsviper import *
>>> MODEL = """
... namespace MyApp {8f14e45f-ceea-467a-9575-1c14b48f0b7e} {
... concept User;
... struct Profile { string city; uint16 age; };
... attachment<User, Profile> profile;
... };
... """
>>> builder = DSMBuilder()
>>> builder.append("model.dsm", MODEL)
>>> report, dsm_defs, defs = builder.parse()
>>> report.has_error()
False
>>> defs.inject(globals()) # MY_APP_T_USER, MY_APP_A_USER_PROFILE, …
>>> key = ValueKey.create(MY_APP_T_USER, "0d2f0e1a-1111-4222-8333-444455556666")
>>> document = Value.create(MY_APP_S_PROFILE, {"city": "Paris", "age": 30})
A CommitDatabase keeps every commit. Mutations are applied to a
CommitMutableState built over the state you start from — a fresh
database has no commit yet, so start from the initial state:
>>> db = CommitDatabase.create_in_memory()
>>> db.extend_definitions(defs).count()
3
>>> last = db.last_commit_id()
>>> state = CommitStateBuilder.state(db, last) if last else CommitStateBuilder.initial_state(db)
>>> mutable = CommitMutableState(state)
>>> mutable.attachment_mutating().set(MY_APP_A_USER_PROFILE, key, document)
>>> commit_id = db.commit_mutations("Add user", mutable)
Reading goes through the state at a commit:
>>> state = CommitStateBuilder.state(db, commit_id)
>>> Value.dumps(state.attachment_getting().get(MY_APP_A_USER_PROFILE, key).unwrap())
{'city': 'Paris', 'age': 30}
A second commit records only what changed:
>>> mutable = CommitMutableState(CommitStateBuilder.state(db, commit_id))
>>> mutable.attachment_mutating().set(
... MY_APP_A_USER_PROFILE, key, Value.create(MY_APP_S_PROFILE, {"city": "Lyon", "age": 31}))
>>> second = db.commit_mutations("Move to Lyon", mutable)
>>> Value.dumps(CommitStateBuilder.state(db, second)
... .attachment_getting().get(MY_APP_A_USER_PROFILE, key).unwrap())
{'city': 'Lyon', 'age': 31}
See also
For detailed examples and the Dual-Layer Contract, see Commit Database and The Dual-Layer Contract.
Path-Based Mutations¶
Use Path with update() to modify specific fields without replacing
the entire document. This enables disjoint concurrent writes — changes to
different fields converge automatically.
from dsviper import CommitDatabase, CommitStateBuilder, CommitMutableState, Path
db = CommitDatabase.open("model.cdb")
db.definitions().inject()
# Build a path to a nested field: document.address.city
path_city = Path.from_field("address").field("city").const()
# Create mutable state
last = db.last_commit_id()
state = CommitStateBuilder.state(db, last) if last else CommitStateBuilder.initial_state(db)
mutable = CommitMutableState(state)
mutating = mutable.attachment_mutating()
# Update only the city field (not the whole document)
mutating.update(MY_APP_A_USER_PROFILE, user_key, path_city, "Paris")
# Commit
db.commit_mutations("Update city", mutable)
With set(), concurrent edits to the same document silently lose one (last-writer-wins). With update(),
edits to different fields converge without loss.
Supervised Reconciliation¶
Reconciling a merge — CommitMergeAnalyzer and friends — is an additive
supervisor over this API, documented on its own page:
Merge Reconciliation.
Database ↔ CommitDatabase Transfer¶
Moving content between the flat Database and the versioned
CommitDatabase — convert, materialize, faithful copy, and flatten — is a
set of converters documented on its own page: Database Transfer.
Choosing the Right Class¶
Use Case |
Class |
Example |
|---|---|---|
Open commit database |
|
|
Read state at specific commit |
|
|
Reduce divergent heads |
|
|
Prepare mutations |
|
|
Read documents (get, keys, has) |
|
|
Write documents (set, update) |
|
|
Inspect commit metadata |
|
|
Core Classes¶
One commit as it is stored. |
|
A Commit database keeps the history of mutations in a DAG of commits. |
|
A low-level class used to represent the database based on SQLite3 through the CommitDatabasing interface. |
|
A low-level class used to represent a remote Commit database through the CommitDatabasing interface. |
|
A CommitDatabaseServer provides network access to a CommitDatabase. |
|
Abstracts the persistence layer behind a Commit database. |
State Access¶
The data reconstructed at one commit, by replaying the mutations down to it. |
|
Registers the mutations of a value executed through the AttachmentMutating interface. |
|
Reconstructs a CommitState from a chosen commit. |
History & DAG¶
One commit in the DAG, linked to the commits that follow it. |
|
One commit's place in the DAG once it is laid out on a grid. |
|
Builds the grid layout of the commit DAG. |
|
What identifies a commit, without its content. |
|
One commit's encoded opcodes, with the header that places it. |
|
A class used by the evaluator to reconstruct a value by executing mutation opcodes. |
|
Navigates the commit DAG. |
Synchronization¶
A high-level application class used to implement the store, dispatch, undo/redo and notification concepts inspired by the redux approach. |
|
An interface used to represent the notification emitted by a store. |
|
Synchronizes two concrete databases through the CommitDatabasing interface (low-level driver interface). |
|
What a synchronization found. |
|
What one synchronization actually transferred. |
|
The commits one database hands another when they synchronize. |
Tracing¶
Asks a state for the trace of one document. |
|
The replay of one document. |
|
One commit's contribution to a document. |