1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! # txn-db
//!
//! A multi-version concurrency control (MVCC) transaction engine: the layer
//! that turns a key-value store into a transactional database.
//!
//! Every write produces a new version tagged with a commit
//! [`Timestamp`], so readers get a stable snapshot of the data without ever
//! blocking writers, and writers detect conflicts at commit time instead of
//! holding locks for the lifetime of a transaction. `txn-db` is deliberately a
//! *layer*, not a store: the version store is the [`VersionStore`] trait, so it
//! composes on top of an LSM tree, a B-tree, or any backend that can keep
//! timestamped versions of a key. Snapshot isolation is the model.
//!
//! ## The common case
//!
//! Begin a transaction, read and write through it, commit. Conflicts surface as
//! a typed, retryable error.
//!
//! ```
//! use txn_db::Db;
//!
//! let db = Db::new();
//!
//! // Write two keys in one atomic transaction.
//! let mut tx = db.begin();
//! tx.put(b"user:1:name".to_vec(), b"ada".to_vec());
//! tx.put(b"user:1:role".to_vec(), b"admin".to_vec());
//! tx.commit()?;
//!
//! // A later transaction reads a consistent snapshot.
//! let tx = db.begin();
//! assert_eq!(tx.get(b"user:1:name")?.as_deref(), Some(&b"ada"[..]));
//! # Ok::<(), txn_db::TxnError>(())
//! ```
//!
//! ## Snapshot isolation
//!
//! A transaction reads the database as of the instant it began. Commits made by
//! other transactions afterward are invisible to it, and its own buffered
//! writes are visible only to itself until it commits. At commit, the engine
//! applies *first-committer-wins*: if any key the transaction wrote was changed
//! by another transaction that committed after this one's snapshot, the commit
//! is rejected with a retryable [`TxnError::Conflict`]. That rule is what
//! prevents lost updates.
//!
//! ```
//! use txn_db::{Db, TxnError};
//!
//! let db = Db::new();
//!
//! // Two transactions start from the same snapshot and write the same key.
//! let mut a = db.begin();
//! let mut b = db.begin();
//! a.put(b"counter".to_vec(), b"1".to_vec());
//! b.put(b"counter".to_vec(), b"2".to_vec());
//!
//! a.commit()?; // the first committer wins
//! let err = b.commit().unwrap_err(); // the second is told to retry
//! assert!(err.is_retryable());
//! # Ok::<(), TxnError>(())
//! ```
//!
//! ## The three tiers
//!
//! - **Tier 1** is the whole common case: [`Db::new`], [`Db::begin`], and the
//! [`Transaction`] methods. No builder, no generics to name.
//! - **Tier 2** is configuration through a builder, arriving in a later phase.
//! - **Tier 3** is the [`VersionStore`] trait, the seam for custom backends,
//! reachable through [`Db::with_store`].
//!
//! ## Status
//!
//! This is the `0.2` foundation: the public surface, the MVCC core, snapshot
//! isolation, and write-write conflict detection over an in-memory store.
//! Serializable isolation, a durable commit log via `wal-db`, and version
//! garbage collection follow in later phases. The shape of the Tier-1 API is
//! settled and will not change before `1.0`.
pub use crateDb;
pub use crate;
pub use crate;
pub use crateTimestamp;
pub use crate;
/// The crate's common imports in one `use`.
///
/// Pulls in the database handle, the transaction and snapshot types, the
/// timestamp, and the error type — everything the Tier-1 common case touches.
///
/// # Examples
///
/// ```
/// use txn_db::prelude::*;
///
/// let db = Db::new();
/// let mut tx = db.begin();
/// tx.put(b"k".to_vec(), b"v".to_vec());
/// let _ts: Timestamp = tx.commit()?;
/// # Ok::<(), TxnError>(())
/// ```