mirror of
https://github.com/clockworklabs/SpacetimeDB.git
synced 2026-05-10 17:49:49 -04:00
52b6c66fa1
# Description of Changes This adds C++ server bindings (/crate/bindings-cpp) to allow writing C++ 20 modules. - Emscripten WASM build system integration with CMake - Macro-based code generation (SPACETIMEDB_TABLE, SPACETIMEDB_REDUCER, etc) - All SpacetimeDB types supported (primitives, Timestamp, Identity, Uuid, etc) - Product types via SPACETIMEDB_STRUCT - Sum types via SPACETIMEDB_ENUM - Constraints marked with FIELD* macros # API and ABI breaking changes None # Expected complexity level and risk 2 - Doesn't heavily impact any other areas but is complex macro C++ structure to support a similar developer experience, did have a small impact on init command # Testing - [x] modules/module-test-cpp - heavily tested every reducer - [x] modules/benchmarks-cpp - tested through the standalone (~6x faster than C#, ~6x slower than Rust) - [x] modules/sdk-test-cpp - [x] modules/sdk-test-procedure-cpp - [x] modules/sdk-test-view-cpp - [x] Wrote several test modules myself - [x] Quickstart smoketest [Currently in progress] - [ ] Write Blackholio C++ server module --------- Signed-off-by: Jason Larabie <jason@clockworklabs.io> Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com> Co-authored-by: Ryan <r.ekhoff@clockworklabs.io> Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com>
120 lines
3.6 KiB
C++
120 lines
3.6 KiB
C++
#ifndef REDUCER_CONTEXT_H
|
|
#define REDUCER_CONTEXT_H
|
|
|
|
#include <spacetimedb/bsatn/types.h> // For Identity, ConnectionId
|
|
#include <spacetimedb/bsatn/timestamp.h> // For Timestamp
|
|
#include <spacetimedb/bsatn/uuid.h> // For Uuid
|
|
#include <spacetimedb/random.h> // For StdbRng
|
|
#include <spacetimedb/auth_ctx.h> // For AuthCtx
|
|
#include <optional>
|
|
#include <array>
|
|
#include <memory>
|
|
|
|
// Include database for DatabaseContext
|
|
#include <spacetimedb/database.h>
|
|
|
|
namespace SpacetimeDB {
|
|
|
|
// Enhanced ReducerContext with database access - matches Rust pattern
|
|
struct ReducerContext {
|
|
// Core fields - directly accessible like in Rust
|
|
Identity sender;
|
|
std::optional<ConnectionId> connection_id;
|
|
Timestamp timestamp;
|
|
|
|
// Database context with name-based access
|
|
DatabaseContext db;
|
|
|
|
private:
|
|
// Authentication context with lazy JWT loading (private like in Rust)
|
|
AuthCtx sender_auth_;
|
|
|
|
// Lazily initialized RNG (similar to Rust's OnceCell pattern)
|
|
// Using shared_ptr to make ReducerContext copyable
|
|
mutable std::shared_ptr<StdbRng> rng_instance;
|
|
|
|
// Monotonic counter for UUID v7 generation (31 bits, wraps around)
|
|
mutable uint32_t counter_uuid_ = 0;
|
|
|
|
public:
|
|
// Returns the authorization information for the caller of this reducer
|
|
const AuthCtx& sender_auth() const {
|
|
return sender_auth_;
|
|
}
|
|
|
|
// Get the random number generator for this reducer call
|
|
// Lazily initialized and seeded with the timestamp
|
|
StdbRng& rng() const {
|
|
if (!rng_instance) {
|
|
rng_instance = std::make_unique<StdbRng>(timestamp);
|
|
}
|
|
return *rng_instance;
|
|
}
|
|
|
|
Identity identity() const {
|
|
std::array<uint8_t, 32> buffer;
|
|
::identity(buffer.data());
|
|
return Identity(buffer);
|
|
}
|
|
|
|
/**
|
|
* Generate a new random UUID v4.
|
|
*
|
|
* Creates a random UUID using the reducer's deterministic RNG.
|
|
*
|
|
* Example:
|
|
* @code
|
|
* SPACETIMEDB_REDUCER(void, create_session, ReducerContext ctx) {
|
|
* Uuid session_id = ctx.new_uuid_v4();
|
|
* ctx.db[sessions].insert(Session{session_id});
|
|
* }
|
|
* @endcode
|
|
*
|
|
* @return A new UUID v4
|
|
*/
|
|
Uuid new_uuid_v4() const {
|
|
// Get 16 random bytes from the context RNG
|
|
std::array<uint8_t, 16> random_bytes;
|
|
rng().fill_bytes(random_bytes.data(), 16);
|
|
|
|
// Generate UUID v4
|
|
return Uuid::from_random_bytes_v4(random_bytes);
|
|
}
|
|
|
|
/**
|
|
* Generate a new UUID v7.
|
|
*
|
|
* Creates a time-ordered UUID with the reducer's timestamp, a monotonic counter,
|
|
* and random bytes from the reducer's deterministic RNG.
|
|
*
|
|
* Example:
|
|
* @code
|
|
* SPACETIMEDB_REDUCER(void, create_user, ReducerContext ctx, std::string name) {
|
|
* Uuid user_id = ctx.new_uuid_v7();
|
|
* ctx.db[users].insert(User{user_id, name});
|
|
* }
|
|
* @endcode
|
|
*
|
|
* @return A new UUID v7
|
|
*/
|
|
Uuid new_uuid_v7() const {
|
|
// Get 4 random bytes from the context RNG
|
|
std::array<uint8_t, 4> random_bytes;
|
|
rng().fill_bytes(random_bytes.data(), 4);
|
|
|
|
// Generate UUID v7 with timestamp and counter
|
|
return Uuid::from_counter_v7(counter_uuid_, timestamp, random_bytes);
|
|
}
|
|
|
|
// Constructors
|
|
ReducerContext() : sender_auth_(AuthCtx::internal()) {}
|
|
|
|
ReducerContext(Identity s, std::optional<ConnectionId> cid, Timestamp ts)
|
|
: sender(s), connection_id(cid), timestamp(ts),
|
|
sender_auth_(AuthCtx::from_connection_id_opt(cid, s)) {}
|
|
};
|
|
|
|
} // namespace SpacetimeDB
|
|
|
|
#endif // REDUCER_CONTEXT_H
|