CommitStore¶
A CommitDatabase is the persistence layer — an immutable DAG of
commits on disk. It exposes mutations, but every read and write goes
through explicit commit ids: there is no “current commit”, no undo
stack, no notifications. Useful as a backing store; awkward as the
core of an interactive application.
CommitStore is the in-memory wrapper that turns a CommitDatabase
into the runtime surface a Commit Application actually uses. It:
owns a current state (the commit a UI is looking at),
dispatches typed mutations as commits,
maintains an undo / redo stack,
notifies observers when any of the above changes,
exposes DAG navigation (multi-head, merge, forward).
This page introduces the four surfaces and points at the references for each. For full method signatures, see the CommitStore API reference.
The four surfaces¶
1. Lifecycle¶
A store starts empty. It is bound to a database (and optionally a specific state) and released the same way:
>>> from dsviper import CommitStore, CommitDatabase
>>> store = CommitStore()
>>> store.use(CommitDatabase.open("model.cdb"))
>>> store.has_database()
True
>>> store.close()
use() is the high-level entry; set_database() / set_state()
exist for finer control (cdbe-style generic editors that decide
“open this database at this commit”). Once a database is attached,
state() returns the current CommitState and mutable_state()
hands out a fresh CommitMutableState to build a commit on top.
2. Dispatch¶
All mutations flow through dispatch. The store builds a mutable
state, runs the callable, persists the resulting commit, advances
the head, and notifies observers — atomically:
>>> store.dispatch(
... "Add Alice",
... lambda m: m.set(TUTO_A_USER_LOGIN, key, login),
... )
Convenience wrappers for the most common shapes:
Method |
What it dispatches |
|---|---|
|
A single |
|
A path-based |
|
The diff of an updated document vs current. |
|
Append an Enable / Disable commit that masks a target. |
The single dispatch surface is what gives the Commit Application Model its Redux-like shape: every state change is an explicit, labelled action against the store, never a sideways write to the database.
4. The notification protocol¶
The store communicates with the UI through CommitStoreNotifying —
a small, framework-agnostic Python protocol. Each platform adapts
it to its own notification mechanism (Qt Signals,
NSNotificationCenter, …). The store never imports a UI framework.
Notification |
When |
|---|---|
|
A database has been attached. |
|
The store has been closed. |
|
The current state moved (commit, undo, navigation). |
|
Definitions extended at runtime. |
|
A dispatched callable raised. |
|
Reset bracket. |
|
Live mode requested to stop. |
A notifier is installed once:
>>> store.set_notifier(my_notifier) # any CommitStoreNotifying impl
The Qt adapter — DSCommitStoreNotifier, which turns each
notification into a Qt Signal — lives in dsviper-components. See
The Notifier Bridge
for the bridge code and the Qt integration recipe.
End-to-end¶
from dsviper import CommitStore, CommitDatabase
store = CommitStore()
store.use(CommitDatabase.open("model.cdb"))
store.set_notifier(my_notifier) # observable
store.dispatch("Add Alice",
lambda m: m.set(TUTO_A_USER_LOGIN, key, login))
assert store.can_undo()
store.undo()
store.redo()
store.close()
A real application wraps this in an Application Context that also holds domain state and the dispatch wiring its UI calls into.
See also¶
Commit Database — the
CommitDatabaseAPI the store sits on.Commit Application Model — the architectural pattern that composes a
CommitStorewith an Application Context.Dual-Layer Contract — the structural guarantees the store relies on and the semantic checks that remain the application’s responsibility.
Component architecture — the Qt adapter for
CommitStoreNotifying.CommitStore API reference — full method signatures.