-
Notifications
You must be signed in to change notification settings - Fork 1k
Expand file tree
/
Copy pathtx_context.h
More file actions
117 lines (107 loc) · 3.94 KB
/
tx_context.h
File metadata and controls
117 lines (107 loc) · 3.94 KB
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
#ifndef SPACETIMEDB_TX_CONTEXT_H
#define SPACETIMEDB_TX_CONTEXT_H
#include <spacetimedb/reducer_context.h>
namespace SpacetimeDB {
/**
* @brief Transaction context for procedures
*
* TxContext wraps a ReducerContext to provide transactional database access.
* It's analogous to Rust's TxContext which is passed to closures in
* `ctx.with_tx()` and `ctx.try_with_tx()`.
*
* Design: Mimics Rust's Deref trait for consistent API
* =====================================================
* In Rust, TxContext implements Deref<Target=ReducerContext>, which means:
* - Reducers use: ctx.db.table()
* - Transactions use: tx.db.table() (Deref auto-dereferences)
*
* C++ doesn't support operator. overloading, so we explicitly expose
* ReducerContext fields as public references to achieve the same ergonomics:
* - Reducers use: ctx.db[table]
* - Transactions use: tx.db[table] (same syntax!)
*
* Tradeoff: TxContext is 40 bytes instead of 8 bytes (storing 5 references),
* but this is negligible as TxContext is stack-allocated and short-lived.
* The consistent API is worth the minor memory cost.
*
* All database operations are part of an anonymous transaction:
* - Transaction commits when the callback returns successfully
* - Transaction rolls back if the callback throws or returns error
*
* Example usage:
* @code
* SPACETIMEDB_PROCEDURE(void, insert_user, ProcedureContext ctx, std::string name) {
* ctx.with_tx([&](TxContext& tx) {
* // Access authentication (same as in reducers)
* if (tx.sender_auth().has_jwt()) {
* auto jwt = tx.sender_auth().get_jwt();
* // ...
* }
* // Database operations here are transactional (same syntax as reducers)
* tx.db[users].insert(User{name});
* });
* }
* @endcode
*/
struct TxContext {
private:
ReducerContext& ctx_;
public:
// Public references to ReducerContext fields for consistent API with Rust
// In Rust, Deref makes tx.db work the same as ctx.db
// In C++, we explicitly expose references where possible and provide
// accessors for fields exposed as methods on ReducerContext.
DatabaseContext& db;
const Timestamp& timestamp;
const std::optional<ConnectionId>& connection_id;
// Constructor - initializes all reference members
explicit TxContext(ReducerContext& ctx)
: ctx_(ctx),
db(ctx.db),
timestamp(ctx.timestamp),
connection_id(ctx.connection_id) {}
// Access to ReducerContext methods
Identity sender() const { return ctx_.sender(); }
const AuthCtx& sender_auth() const { return ctx_.sender_auth(); }
Identity identity() const { return ctx_.identity(); }
StdbRng& rng() const { return ctx_.rng(); }
/**
* Generate a new random UUID v4.
*
* Creates a random UUID using the transaction's deterministic RNG.
*
* Example:
* @code
* SPACETIMEDB_PROCEDURE(void, create_session, ProcedureContext ctx) {
* ctx.with_tx([&](TxContext& tx) {
* Uuid session_id = tx.new_uuid_v4();
* tx.db[sessions].insert(Session{session_id});
* });
* }
* @endcode
*
* @return A new UUID v4
*/
Uuid new_uuid_v4() const { return ctx_.new_uuid_v4(); }
/**
* Generate a new UUID v7.
*
* Creates a time-ordered UUID with the transaction's timestamp, a monotonic counter,
* and random bytes from the transaction's deterministic RNG.
*
* Example:
* @code
* SPACETIMEDB_PROCEDURE(void, create_user, ProcedureContext ctx, std::string name) {
* ctx.with_tx([&](TxContext& tx) {
* Uuid user_id = tx.new_uuid_v7();
* tx.db[users].insert(User{user_id, name});
* });
* }
* @endcode
*
* @return A new UUID v7
*/
Uuid new_uuid_v7() const { return ctx_.new_uuid_v7(); }
};
} // namespace SpacetimeDB
#endif // SPACETIMEDB_TX_CONTEXT_H