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
//! `turnframe-store`: the persistence contract of Turnframe, plus a
//! deterministic in-memory implementation and an executable conformance suite.
//!
//! It defines *what* must be durable and *with which rules*, as seven
//! object-safe traits, and nothing about *where*: no driver, no SQL. The
//! PostgreSQL adapter is one implementation and is optional. The rules an
//! implementation must honour — total account scoping, a closed error surface,
//! compare-and-swap instead of blind overwrite, immutability, specified
//! ordering — and the all-or-nothing commit model are in
//! [`docs/persistence.md`](https://github.com/turnframe-rs/turnframe/blob/main/docs/persistence.md).
//! [`conformance::run_all`] proves an implementation right without reading its
//! code, and [`MemoryStores`] is the reference one.
//!
//! Six traits are split into a `…Reader` and a `…Writer` half, aggregated by
//! the trait carrying the historical name, so a caller that must not write can
//! be handed [`ReadOnlyStores`] and the compiler keeps it that way.
//! [`Stores`] bundles one implementation of each.
//!
//! | Trait | Module | What it owns |
//! |---|---|---|
//! | [`ConversationStore`](conversation::ConversationStore) | [`conversation`] | conversations, user turns, assistant turns *as returned*, the crash-recovery phase marker |
//! | [`InteractionStore`](interaction::InteractionStore) | [`interaction`] | persisted cards: payloads, the one-blocking-per-case slot, compare-and-swap resolution, expiry |
//! | [`CommandJournal`](journal::CommandJournal) | [`journal`] | idempotency admission and the persisted outcome of every command |
//! | [`EventJournal`](events::EventJournal) | [`events`] | the append-only claim ledger, paged exactly once, erasable only by redaction |
//! | [`OutboxStore`](outbox::OutboxStore) | [`outbox`] | external side effects awaiting dispatch, with claim/reschedule semantics |
//! | [`ReplayStore`](replay::ReplayStore) | [`replay`] | one replay record per turn, upserted as the turn advances |
//! | [`CommitStore`](commit::CommitStore) | [`commit`] | the all-or-nothing write of everything one commit produces |
//!
//! # Example
//!
//! ```rust
//! use turnframe_core::ids::{AccountId, ConversationId};
//! use turnframe_store::prelude::*;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # tokio::runtime::Runtime::new()?.block_on(async {
//! let stores = Stores::in_memory();
//! let account = AccountId::from("aurora");
//! let conversation = ConversationId::new();
//! let now = chrono::Utc::now();
//!
//! stores
//! .conversations()
//! .create_conversation(ConversationRecord::new(
//! conversation,
//! account.clone(),
//! now,
//! ))
//! .await?;
//!
//! let loaded = stores
//! .conversations()
//! .load_conversation(&account, &conversation)
//! .await?;
//! assert_eq!(loaded.account_id, account);
//!
//! // Another tenant cannot tell it apart from one that never existed.
//! let other = AccountId::from("other");
//! assert_eq!(
//! stores
//! .conversations()
//! .load_conversation(&other, &conversation)
//! .await,
//! Err(StoreError::NotFound)
//! );
//! # Ok::<(), StoreError>(())
//! # })?;
//! # Ok(())
//! # }
//! ```
/// The crate README, compiled as a doc-test so its examples cannot rot.
// The handful of names an application says out loud, at the crate root, so a
// caller writes `turnframe_store::Stores` rather than `stores::Stores` through
// a module whose name repeats the type's. The modules stay public for
// everything else.
pub use crate;
pub use crate;
pub use crate;
/// The items an application needs to hold and use a set of stores.
///
/// Adapter authors additionally want the record and outcome types from the
/// individual modules; this prelude carries the traits, the aggregate, the
/// error surface and the in-memory implementation.