mirror of
https://github.com/clockworklabs/SpacetimeDB.git
synced 2026-06-28 16:58:39 -04:00
c7af2d4cd3
## Summary - add `ReducerContext::database_identity()` in Rust bindings - deprecate `ReducerContext::identity()` and keep it as a compatibility alias - update reducer docs example to use `ctx.database_identity()` - add C# reducer-context equivalent: `DatabaseIdentity` and obsolete `Identity` alias - update Rust/C# module test callsites to the new API name - update C# codegen snapshots for generated `ReducerContext` API output ## Why Issue #3201 reports user confusion between reducer `ctx.identity()` (database/module identity) and `ctx.sender`. This change clarifies naming while preserving compatibility. ## Validation - `cargo check -p spacetimedb -p module-test` (Passed) - `dotnet test crates/bindings-csharp/Codegen.Tests/Codegen.Tests.csproj --nologo` (Passed) - `dotnet test crates/bindings-csharp/Runtime.Tests/Runtime.Tests.csproj --nologo` (Failed) pre-existing unrelated failure: - `Runtime.Tests/JwtClaimsTest.cs(10,23): CS1729: 'JwtClaims' does not contain a constructor that takes 2 arguments` ## Compatibility - Rust: `identity()` still works but is deprecated in favor of `database_identity()`. - C#: `Identity` still works but is marked `[Obsolete]` in favor of `DatabaseIdentity`. Closes #3201
120 lines
4.1 KiB
C++
120 lines
4.1 KiB
C++
#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 database_identity() const { return ctx_.database_identity(); }
|
|
[[deprecated("Use database_identity() instead.")]]
|
|
Identity identity() const { return database_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
|