From d5e19a743f79582a37ff46ff7699ee0a0ecce502 Mon Sep 17 00:00:00 2001 From: Tyler Cloutier Date: Mon, 1 Jun 2026 19:46:40 -0400 Subject: [PATCH 1/3] Ungate procedures from the `unstable` feature Procedures (and the outgoing HTTP client used from procedures) are no longer gated behind the `unstable` feature / `SPACETIMEDB_UNSTABLE_FEATURES` across the module libraries. HTTP handlers/webhooks, views, RLS, and immediate-scheduling remain gated. - bindings-sys: ungate the `procedure` host-call module + raw ABI (start/commit/abort_mut_tx, procedure_http_request) and `call_no_ret`. - bindings (Rust): ungate the `procedure` macro, ProcedureContext, TxContext/with_tx/try_with_tx, db_read_only/get_read_only, procedure traits, register_procedure, __call_procedure__, procedure RNG, and the outgoing HttpClient. Add fine-grained gating inside http.rs so the HttpClient is exposed while HandlerContext/Router/handler macros stay gated. - bindings-csharp: drop [Experimental("STDB_UNSTABLE")] from ProcedureContext WithTx/TryWithTx (runtime + generated) and the generated ProcedureTxContext; regenerate FFI snapshots. - bindings-cpp: ungate the procedure ABI, tx_execution, the outgoing HTTP client (http.h/http_convert.h), and procedure_context.h; handlers keep requiring SPACETIMEDB_UNSTABLE_FEATURES. - docs: remove the procedures beta notices (HTTP handlers stay beta); regenerate static/llms.md. - sdk-test-procedure: no longer needs features = ["unstable"]. --- .../include/spacetimedb/abi/FFI.h | 2 - .../include/spacetimedb/abi/abi.h | 2 - .../bindings-cpp/include/spacetimedb/http.h | 10 +--- .../include/spacetimedb/http_convert.h | 2 - .../spacetimedb/internal/tx_execution.h | 4 -- .../include/spacetimedb/procedure_context.h | 8 +--- .../diag/snapshots/Module#FFI.verified.cs | 4 -- .../snapshots/Module#FFI.verified.cs | 4 -- .../server/snapshots/Module#FFI.verified.cs | 4 -- crates/bindings-csharp/Codegen/Module.cs | 8 +--- .../Runtime/ProcedureContext.cs | 4 -- crates/bindings-sys/src/lib.rs | 5 -- crates/bindings/src/http.rs | 46 +++++++++++++++---- crates/bindings/src/lib.rs | 22 +-------- crates/bindings/src/rng.rs | 6 +-- crates/bindings/src/rt.rs | 38 ++------------- .../00400-key-architecture.md | 2 - .../00100-getting-started/00500-faq.md | 2 +- .../00200-core-concepts/00200-functions.md | 2 +- .../00200-functions/00400-procedures.md | 4 -- .../docs/00200-core-concepts/00600-clients.md | 2 +- .../00600-clients/00200-codegen.md | 2 +- docs/static/llms.md | 18 +++++++- modules/sdk-test-procedure/Cargo.toml | 1 - 24 files changed, 69 insertions(+), 133 deletions(-) diff --git a/crates/bindings-cpp/include/spacetimedb/abi/FFI.h b/crates/bindings-cpp/include/spacetimedb/abi/FFI.h index 23064a518f2..32990f156d4 100644 --- a/crates/bindings-cpp/include/spacetimedb/abi/FFI.h +++ b/crates/bindings-cpp/include/spacetimedb/abi/FFI.h @@ -75,11 +75,9 @@ using ::identity; using ::get_jwt; // ===== Procedure Transactions ===== -#ifdef SPACETIMEDB_UNSTABLE_FEATURES using ::procedure_start_mut_tx; using ::procedure_commit_mut_tx; using ::procedure_abort_mut_tx; -#endif // ===== Module Export Helpers ===== diff --git a/crates/bindings-cpp/include/spacetimedb/abi/abi.h b/crates/bindings-cpp/include/spacetimedb/abi/abi.h index e1aa12ac2de..99dc067c147 100644 --- a/crates/bindings-cpp/include/spacetimedb/abi/abi.h +++ b/crates/bindings-cpp/include/spacetimedb/abi/abi.h @@ -174,7 +174,6 @@ STDB_IMPORT_10_2(get_jwt) Status get_jwt(const uint8_t* connection_id_ptr, BytesSource* out); // ===== Procedure Transactions (spacetime_10.3) ===== -#ifdef SPACETIMEDB_UNSTABLE_FEATURES STDB_IMPORT_10_3(procedure_start_mut_tx) Status procedure_start_mut_tx(int64_t* out); @@ -190,7 +189,6 @@ Status procedure_http_request( const uint8_t* request_ptr, size_t request_len, const uint8_t* body_ptr, size_t body_len, BytesSource out[2]); -#endif } // extern "C" diff --git a/crates/bindings-cpp/include/spacetimedb/http.h b/crates/bindings-cpp/include/spacetimedb/http.h index 82a55beeb32..229e7081d3d 100644 --- a/crates/bindings-cpp/include/spacetimedb/http.h +++ b/crates/bindings-cpp/include/spacetimedb/http.h @@ -3,10 +3,6 @@ #pragma once -#ifndef SPACETIMEDB_UNSTABLE_FEATURES -#error "spacetimedb/http.h requires SPACETIMEDB_UNSTABLE_FEATURES to be enabled" -#endif - #include #include #include @@ -302,12 +298,8 @@ class HttpClient { * @endcode */ Outcome send(const HttpRequest& request) { - #ifndef SPACETIMEDB_UNSTABLE_FEATURES - return Err("HTTP requests require SPACETIMEDB_UNSTABLE_FEATURES to be enabled"); - #else // Implemented in http_client_impl.h to avoid circular dependencies return SendImpl(request); - #endif } private: @@ -317,7 +309,7 @@ class HttpClient { } // namespace SpacetimeDB // Include implementation dependencies after class definition to avoid circular dependencies -#if defined(SPACETIMEDB_UNSTABLE_FEATURES) && !defined(SPACETIMEDB_HTTP_CONVERT_H) +#ifndef SPACETIMEDB_HTTP_CONVERT_H #include "spacetimedb/logger.h" #include "spacetimedb/http_convert.h" #include "spacetimedb/http_client_impl.h" diff --git a/crates/bindings-cpp/include/spacetimedb/http_convert.h b/crates/bindings-cpp/include/spacetimedb/http_convert.h index e514f4b864e..40f11b687c5 100644 --- a/crates/bindings-cpp/include/spacetimedb/http_convert.h +++ b/crates/bindings-cpp/include/spacetimedb/http_convert.h @@ -281,9 +281,7 @@ inline std::pair> to_wire_split(const H } // namespace convert } // namespace SpacetimeDB -#ifdef SPACETIMEDB_UNSTABLE_FEATURES #include "spacetimedb/logger.h" #include "spacetimedb/http_client_impl.h" -#endif #endif // SPACETIMEDB_HTTP_CONVERT_H diff --git a/crates/bindings-cpp/include/spacetimedb/internal/tx_execution.h b/crates/bindings-cpp/include/spacetimedb/internal/tx_execution.h index 4f0f8db2d0c..cd58bf3ed44 100644 --- a/crates/bindings-cpp/include/spacetimedb/internal/tx_execution.h +++ b/crates/bindings-cpp/include/spacetimedb/internal/tx_execution.h @@ -9,8 +9,6 @@ namespace SpacetimeDB::Internal { -#ifdef SPACETIMEDB_UNSTABLE_FEATURES - template struct is_outcome : std::false_type {}; @@ -143,8 +141,6 @@ auto try_with_tx(MakeReducerContext&& make_reducer_ctx, Func& body) -> decltype( return result; } -#endif - } // namespace SpacetimeDB::Internal #endif // SPACETIMEDB_INTERNAL_TX_EXECUTION_H diff --git a/crates/bindings-cpp/include/spacetimedb/procedure_context.h b/crates/bindings-cpp/include/spacetimedb/procedure_context.h index ea189f8ef12..ebfd958af7c 100644 --- a/crates/bindings-cpp/include/spacetimedb/procedure_context.h +++ b/crates/bindings-cpp/include/spacetimedb/procedure_context.h @@ -8,9 +8,7 @@ #include // For transaction syscalls #include #include // For StdbRng -#ifdef SPACETIMEDB_UNSTABLE_FEATURES #include // For HttpClient -#endif #include #include #include @@ -66,12 +64,10 @@ struct ProcedureContext { // Used to track which client connection initiated this procedure ConnectionId connection_id; -#ifdef SPACETIMEDB_UNSTABLE_FEATURES // HTTP client for making external requests // IMPORTANT: HTTP calls are NOT allowed inside transactions! // Always call HTTP before with_tx() or try_with_tx() HttpClient http; -#endif private: // Lazily initialized RNG for UUID generation @@ -173,10 +169,9 @@ struct ProcedureContext { return Uuid::from_counter_v7(counter_uuid_, timestamp, random_bytes); } -#ifdef SPACETIMEDB_UNSTABLE_FEATURES /** * @brief Execute a callback within a database transaction - * + * * Starts a mutable transaction, executes the callback, and commits on success. * If the callback panics (via LOG_PANIC), the transaction is automatically rolled back. * @@ -238,7 +233,6 @@ struct ProcedureContext { }; return Internal::try_with_tx(make_reducer_ctx, body); } -#endif }; } // namespace SpacetimeDB diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs index 2504cc013bf..10a1d4e0b64 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs @@ -749,14 +749,11 @@ Internal.TxContext inner private ProcedureTxContext? _cached; - [Experimental("STDB_UNSTABLE")] public Local Db => _db; - [Experimental("STDB_UNSTABLE")] public TResult WithTx(Func body) => base.WithTx(tx => body((ProcedureTxContext)tx)); - [Experimental("STDB_UNSTABLE")] public TxOutcome TryWithTx( Func> body ) @@ -850,7 +847,6 @@ public Uuid NewUuidV7() } } - [Experimental("STDB_UNSTABLE")] public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase { internal ProcedureTxContext(Internal.TxContext inner) diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs index b46de3189b4..76adb1188bb 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/explicitnames/snapshots/Module#FFI.verified.cs @@ -151,14 +151,11 @@ Internal.TxContext inner private ProcedureTxContext? _cached; - [Experimental("STDB_UNSTABLE")] public Local Db => _db; - [Experimental("STDB_UNSTABLE")] public TResult WithTx(Func body) => base.WithTx(tx => body((ProcedureTxContext)tx)); - [Experimental("STDB_UNSTABLE")] public TxOutcome TryWithTx( Func> body ) @@ -252,7 +249,6 @@ public Uuid NewUuidV7() } } - [Experimental("STDB_UNSTABLE")] public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase { internal ProcedureTxContext(Internal.TxContext inner) diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs index edc7d5f2af4..da074b5e5f8 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs @@ -593,14 +593,11 @@ Internal.TxContext inner private ProcedureTxContext? _cached; - [Experimental("STDB_UNSTABLE")] public Local Db => _db; - [Experimental("STDB_UNSTABLE")] public TResult WithTx(Func body) => base.WithTx(tx => body((ProcedureTxContext)tx)); - [Experimental("STDB_UNSTABLE")] public TxOutcome TryWithTx( Func> body ) @@ -694,7 +691,6 @@ public Uuid NewUuidV7() } } - [Experimental("STDB_UNSTABLE")] public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase { internal ProcedureTxContext(Internal.TxContext inner) diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 870cadce093..dde6edee808 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -2545,14 +2545,11 @@ internal ProcedureContext(Identity identity, ConnectionId? connectionId, Random private ProcedureTxContext? _cached; - [Experimental("STDB_UNSTABLE")] public Local Db => _db; - - [Experimental("STDB_UNSTABLE")] + public TResult WithTx(Func body) => base.WithTx(tx => body((ProcedureTxContext)tx)); - - [Experimental("STDB_UNSTABLE")] + public TxOutcome TryWithTx( Func> body) where TError : Exception => @@ -2643,7 +2640,6 @@ public Uuid NewUuidV7() } } - [Experimental("STDB_UNSTABLE")] public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase { internal ProcedureTxContext(Internal.TxContext inner) : base(inner) {} diff --git a/crates/bindings-csharp/Runtime/ProcedureContext.cs b/crates/bindings-csharp/Runtime/ProcedureContext.cs index 9c5a197aa1e..a86711f2814 100644 --- a/crates/bindings-csharp/Runtime/ProcedureContext.cs +++ b/crates/bindings-csharp/Runtime/ProcedureContext.cs @@ -1,7 +1,5 @@ namespace SpacetimeDB; -using System.Diagnostics.CodeAnalysis; - #pragma warning disable STDB_UNSTABLE public abstract class ProcedureContextBase : Internal.IInternalProcedureContext { @@ -75,11 +73,9 @@ public TResult UnwrapOrThrow(Func fallbackFactory) => IsSuccess ? Value! : throw (Error ?? fallbackFactory()); } - [Experimental("STDB_UNSTABLE")] public TResult WithTx(Func body) => txState.WithTx(body); - [Experimental("STDB_UNSTABLE")] public TxOutcome TryWithTx( Func> body ) diff --git a/crates/bindings-sys/src/lib.rs b/crates/bindings-sys/src/lib.rs index b31c4d0a451..566b2079ebb 100644 --- a/crates/bindings-sys/src/lib.rs +++ b/crates/bindings-sys/src/lib.rs @@ -644,7 +644,6 @@ pub mod raw { pub fn get_jwt(connection_id_ptr: *const u8, bytes_source_id: *mut BytesSource) -> u16; } - #[cfg(feature = "unstable")] #[link(wasm_import_module = "spacetime_10.3")] unsafe extern "C" { /// Suspends execution of this WASM instance until approximately `wake_at_micros_since_unix_epoch`. @@ -775,7 +774,6 @@ pub mod raw { /// - `body_ptr` is NULL or `body_ptr[..body_len]` is not in bounds of WASM memory. /// - `out` is NULL or `out[..size_of::()]` is not in bounds of WASM memory. /// - `request_ptr[..request_len]` does not contain a valid BSATN-serialized `spacetimedb_lib::http::Request` object. - #[cfg(feature = "unstable")] pub fn procedure_http_request( request_ptr: *const u8, request_len: u32, @@ -1072,7 +1070,6 @@ unsafe fn call(f: impl FnOnce(*mut T) -> u16) -> Result { /// Assuming the call to `f` returns 0, `Ok(())` is returned, /// and otherwise `Err(err)` is returned. #[inline] -#[cfg(feature = "unstable")] fn call_no_ret(f: impl FnOnce() -> u16) -> Result<()> { let f_code = f(); cvt(f_code)?; @@ -1548,7 +1545,6 @@ impl Drop for RowIter { } } -#[cfg(feature = "unstable")] pub mod procedure { //! Side-effecting or asynchronous operations which only procedures are allowed to perform. @@ -1624,7 +1620,6 @@ pub mod procedure { } #[inline] - #[cfg(feature = "unstable")] /// Perform an HTTP request as specified by `http_request_bsatn`, /// suspending execution until the request is complete, /// then return its response or error. diff --git a/crates/bindings/src/http.rs b/crates/bindings/src/http.rs index a0ee89819ba..bf6b18eae2c 100644 --- a/crates/bindings/src/http.rs +++ b/crates/bindings/src/http.rs @@ -5,19 +5,31 @@ //! The [`get`](HttpClient::get) helper can be used for simple `GET` requests, //! while [`send`](HttpClient::send) allows more complex requests with headers, bodies and other methods. -use crate::{ - rt::{read_bytes_source_as, read_bytes_source_into}, - try_with_tx, with_tx, IterBuf, StdbRng, Timestamp, TxContext, -}; +use crate::rt::{read_bytes_source_as, read_bytes_source_into}; +use crate::IterBuf; +// Imports used only by the (still-unstable) HTTP handler machinery. +#[cfg(feature = "unstable")] +use crate::{try_with_tx, with_tx, Timestamp, TxContext}; +#[cfg(all(feature = "unstable", feature = "rand08"))] +use crate::StdbRng; use bytes::Bytes; -#[cfg(feature = "rand")] +#[cfg(all(feature = "rand", feature = "unstable"))] use rand08::RngCore; +#[cfg(feature = "unstable")] use spacetimedb_lib::db::raw_def::v10::MethodOrAny; -use spacetimedb_lib::http::{ - self as st_http, character_is_acceptable_for_route_path, ACCEPTABLE_ROUTE_PATH_CHARS_HUMAN_DESCRIPTION, -}; -use spacetimedb_lib::{bsatn, Identity, TimeDuration, Uuid}; -use std::cell::{Cell, OnceCell}; +use spacetimedb_lib::http as st_http; +#[cfg(feature = "unstable")] +use spacetimedb_lib::http::{character_is_acceptable_for_route_path, ACCEPTABLE_ROUTE_PATH_CHARS_HUMAN_DESCRIPTION}; +use spacetimedb_lib::{bsatn, TimeDuration}; +#[cfg(feature = "unstable")] +use spacetimedb_lib::Identity; +#[cfg(all(feature = "unstable", feature = "rand"))] +use spacetimedb_lib::Uuid; +#[cfg(all(feature = "unstable", feature = "rand"))] +use std::cell::Cell; +#[cfg(all(feature = "unstable", feature = "rand08"))] +use std::cell::OnceCell; +#[cfg(feature = "unstable")] use std::str::FromStr; pub type Request = http::Request; @@ -54,6 +66,7 @@ pub type Response = http::Response; /// hello_world(ctx, req); // Won't compile, as our handler `hello_world`'s function was shadowed. /// # } /// ``` +#[cfg(feature = "unstable")] #[doc(inline)] pub use spacetimedb_bindings_macro::http_handler as handler; @@ -72,6 +85,7 @@ pub use spacetimedb_bindings_macro::http_handler as handler; /// Router::new().get("/hello-world", hello_world) /// } /// ``` +#[cfg(feature = "unstable")] #[doc(inline)] pub use spacetimedb_bindings_macro::http_router as router; @@ -81,6 +95,7 @@ pub use spacetimedb_bindings_macro::http_router as router; /// /// Includes the time of invocation and exposes methods for running transactions /// and performing side-effecting operations. +#[cfg(feature = "unstable")] #[non_exhaustive] pub struct HandlerContext { /// The time at which the handler was started. @@ -98,6 +113,7 @@ pub struct HandlerContext { pub(crate) counter_uuid: Cell, } +#[cfg(feature = "unstable")] impl HandlerContext { pub(crate) fn new(timestamp: Timestamp) -> Self { Self { @@ -146,11 +162,13 @@ impl HandlerContext { /// /// The [`handler`] macro will define a constant of type [`Handler`], /// which can be used to refer to the handler function when registering it to handle a route. +#[cfg(feature = "unstable")] #[derive(Clone, Copy)] pub struct Handler { name: &'static str, } +#[cfg(feature = "unstable")] impl Handler { /// Emitted by the [`handler`] macro. /// @@ -199,11 +217,13 @@ impl Handler { /// ## Registering /// /// Register a `Handler` as the root handler of your database with the [`handler` macro](macro@handler). +#[cfg(feature = "unstable")] #[derive(Clone, Default)] pub struct Router { routes: Vec, } +#[cfg(feature = "unstable")] #[derive(Clone)] pub(crate) struct RouteSpec { pub method: MethodOrAny, @@ -211,6 +231,7 @@ pub(crate) struct RouteSpec { pub handler: Handler, } +#[cfg(feature = "unstable")] impl Router { /// Returns a new, empty `Router`. pub fn new() -> Self { @@ -365,6 +386,7 @@ impl Router { } } +#[cfg(feature = "unstable")] fn join_paths(prefix: &str, suffix: &str) -> String { if prefix == "/" { return suffix.to_string(); @@ -377,6 +399,7 @@ fn join_paths(prefix: &str, suffix: &str) -> String { format!("{prefix}/{suffix}") } +#[cfg(feature = "unstable")] fn assert_valid_path(path: &str) { if !path.is_empty() && !path.starts_with('/') { panic!("Route paths must start with `/`: {path}"); @@ -389,6 +412,7 @@ fn assert_valid_path(path: &str) { } } +#[cfg(feature = "unstable")] fn routes_overlap(a: &RouteSpec, b: &RouteSpec) -> bool { if a.path != b.path { return false; @@ -578,6 +602,7 @@ fn convert_response(response: st_http::Response) -> http::Result http::Request { let st_http::Request { method, @@ -628,6 +653,7 @@ pub(crate) fn request_from_wire(request: st_http::Request, body: Bytes) -> http: http::Request::from_parts(parts, body) } +#[cfg(feature = "unstable")] pub(crate) fn response_into_wire(response: http::Response) -> (st_http::Response, Bytes) { let (parts, body) = response.into_parts(); let st_response = st_http::Response { diff --git a/crates/bindings/src/lib.rs b/crates/bindings/src/lib.rs index abc972748dd..0f668d05282 100644 --- a/crates/bindings/src/lib.rs +++ b/crates/bindings/src/lib.rs @@ -8,7 +8,6 @@ use std::rc::Rc; #[cfg(feature = "unstable")] mod client_visibility_filter; -#[cfg(feature = "unstable")] pub mod http; pub mod log_stopwatch; mod logger; @@ -772,7 +771,6 @@ pub use spacetimedb_bindings_macro::reducer; /// [clients]: https://spacetimedb.com/docs/#client // TODO(procedure-async): update docs and examples with `async`-ness. #[doc(inline)] -#[cfg(feature = "unstable")] pub use spacetimedb_bindings_macro::procedure; /// Marks a function as a spacetimedb view. @@ -1153,7 +1151,6 @@ impl ReducerContext { } } -#[cfg(feature = "unstable")] /// The context that an anonymous transaction /// in [`ProcedureContext::with_tx`] is provided with. /// @@ -1167,14 +1164,12 @@ impl ReducerContext { /// Implements the `DbContext` trait for accessing views into a database. pub struct TxContext(ReducerContext); -#[cfg(feature = "unstable")] impl AsRef for TxContext { fn as_ref(&self) -> &ReducerContext { &self.0 } } -#[cfg(feature = "unstable")] impl Deref for TxContext { type Target = ReducerContext; @@ -1183,7 +1178,6 @@ impl Deref for TxContext { } } -#[cfg(feature = "unstable")] fn try_with_tx(body: impl Fn(&TxContext) -> Result) -> Result { let abort = || { crate::sys::procedure::procedure_abort_mut_tx() @@ -1229,7 +1223,6 @@ fn try_with_tx(body: impl Fn(&TxContext) -> Result) -> Result res } -#[cfg(feature = "unstable")] fn with_tx(body: impl Fn(&TxContext) -> T) -> T { use core::convert::Infallible; match try_with_tx::(|tx| Ok(body(tx))) { @@ -1245,7 +1238,6 @@ fn with_tx(body: impl Fn(&TxContext) -> T) -> T { /// Includes information about the client calling the procedure and the time of invocation, /// and exposes methods for running transactions and performing side-effecting operations. #[non_exhaustive] -#[cfg(feature = "unstable")] pub struct ProcedureContext { /// The `Identity` of the client that invoked the procedure. sender: Identity, @@ -1272,7 +1264,6 @@ pub struct ProcedureContext { counter_uuid: Cell, } -#[cfg(feature = "unstable")] impl ProcedureContext { fn new(sender: Identity, connection_id: Option, timestamp: Timestamp) -> Self { Self { @@ -1333,7 +1324,6 @@ impl ProcedureContext { /// # } /// ``` // TODO(procedure-sleep-until): remove this method - #[cfg(feature = "unstable")] pub fn sleep_until(&mut self, timestamp: Timestamp) { let new_time = sys::procedure::sleep_until(timestamp.to_micros_since_unix_epoch()); let new_time = Timestamp::from_micros_since_unix_epoch(new_time); @@ -1366,7 +1356,6 @@ impl ProcedureContext { /// and return the same result on each invocation, /// callers should avoid writing to any captured mutable state within `body`, /// This includes interior mutability through types like [`std::cell::Cell`]. - #[cfg(feature = "unstable")] pub fn with_tx(&mut self, body: impl Fn(&TxContext) -> T) -> T { with_tx(body) } @@ -1400,7 +1389,6 @@ impl ProcedureContext { /// and return the same result on each invocation, /// callers should avoid writing to any captured mutable state within `body`, /// This includes interior mutability through types like [`std::cell::Cell`]. - #[cfg(feature = "unstable")] pub fn try_with_tx(&mut self, body: impl Fn(&TxContext) -> Result) -> Result { try_with_tx(body) } @@ -1419,7 +1407,7 @@ impl ProcedureContext { /// } /// # } /// ``` - #[cfg(all(feature = "unstable", feature = "rand"))] + #[cfg(feature = "rand")] pub fn new_uuid_v4(&self) -> anyhow::Result { let mut bytes = [0u8; 16]; self.rng().try_fill_bytes(&mut bytes)?; @@ -1441,7 +1429,7 @@ impl ProcedureContext { /// } /// # } /// ``` - #[cfg(all(feature = "unstable", feature = "rand"))] + #[cfg(feature = "rand")] pub fn new_uuid_v7(&self) -> anyhow::Result { let mut random_bytes = [0u8; 4]; self.rng().try_fill_bytes(&mut random_bytes)?; @@ -1468,7 +1456,6 @@ pub trait DbContext { /// /// This method is provided for times when a programmer wants to be generic over the `DbContext` type. /// Concrete-typed code is expected to read the `.db` field off the particular `DbContext` implementor. - #[cfg(feature = "unstable")] fn db_read_only(&self) -> &LocalReadOnly; } @@ -1479,7 +1466,6 @@ impl DbContext for AnonymousViewContext { &self.db } - #[cfg(feature = "unstable")] fn db_read_only(&self) -> &LocalReadOnly { &self.db } @@ -1492,13 +1478,11 @@ impl DbContext for ReducerContext { &self.db } - #[cfg(feature = "unstable")] fn db_read_only(&self) -> &LocalReadOnly { self.db.get_read_only() } } -#[cfg(feature = "unstable")] impl DbContext for TxContext { type DbView = Local; @@ -1518,7 +1502,6 @@ impl DbContext for ViewContext { &self.db } - #[cfg(feature = "unstable")] fn db_read_only(&self) -> &LocalReadOnly { &self.db } @@ -1536,7 +1519,6 @@ impl DbContext for ViewContext { pub struct Local {} impl Local { - #[cfg(feature = "unstable")] fn get_read_only(&self) -> &LocalReadOnly { &LocalReadOnly {} } diff --git a/crates/bindings/src/rng.rs b/crates/bindings/src/rng.rs index d9ed0bf65d7..a883030e43e 100644 --- a/crates/bindings/src/rng.rs +++ b/crates/bindings/src/rng.rs @@ -1,5 +1,6 @@ +use crate::ProcedureContext; #[cfg(feature = "unstable")] -use crate::{http::HandlerContext, ProcedureContext}; +use crate::http::HandlerContext; use crate::{rand, ReducerContext}; use core::cell::UnsafeCell; use core::marker::PhantomData; @@ -51,14 +52,12 @@ impl ReducerContext { } } -#[cfg(feature = "unstable")] impl ProcedureContext { /// Generates a random value. /// /// Similar to [`rand::random()`], but using [`StdbRng`] instead. /// /// See also [`ProcedureContext::rng()`]. - #[cfg(feature = "unstable")] pub fn random(&self) -> T where Standard: Distribution, @@ -90,7 +89,6 @@ impl ProcedureContext { /// ``` /// /// For more information, see [`StdbRng`] and [`rand::Rng`]. - #[cfg(feature = "unstable")] pub fn rng(&self) -> &StdbRng { self.rng.get_or_init(|| StdbRng::seed_from_ts(self.timestamp)) } diff --git a/crates/bindings/src/rt.rs b/crates/bindings/src/rt.rs index 79543f4a925..29c0c833d8c 100644 --- a/crates/bindings/src/rt.rs +++ b/crates/bindings/src/rt.rs @@ -21,11 +21,9 @@ use std::marker::PhantomData; use std::sync::{Mutex, OnceLock}; pub use sys::raw::{BytesSink, BytesSource}; +use crate::{ProcedureContext, ProcedureResult}; #[cfg(feature = "unstable")] -use crate::{ - http::{self, HandlerContext}, - ProcedureContext, ProcedureResult, -}; +use crate::http::{self, HandlerContext}; pub trait IntoVec { fn into_vec(self) -> Vec; @@ -58,7 +56,6 @@ pub fn invoke_reducer<'a, A: Args<'a>>( reducer.invoke(ctx, args) } -#[cfg(feature = "unstable")] pub fn invoke_procedure<'a, A: Args<'a>, Ret: IntoProcedureResult>( procedure: impl Procedure<'a, A, Ret>, ctx: &mut ProcedureContext, @@ -150,11 +147,7 @@ pub trait FnInfo: ExplicitNames { /// The type of function to invoke. type Invoke; - #[cfg_attr( - feature = "unstable", - doc = "One of [`FnKindReducer`], [`FnKindProcedure`] or [`FnKindView`]." - )] - #[cfg_attr(not(feature = "unstable"), doc = "Either [`FnKindReducer`] or [`FnKindView`].")] + /// One of [`FnKindReducer`], [`FnKindProcedure`] or [`FnKindView`]. /// /// Used as a type argument to [`ExportFunctionForScheduledTable`] and [`scheduled_typecheck`]. /// See for details on this technique. @@ -179,7 +172,6 @@ pub trait FnInfo: ExplicitNames { } } -#[cfg(feature = "unstable")] pub trait Procedure<'de, A: Args<'de>, Ret: IntoProcedureResult> { fn invoke(&self, ctx: &mut ProcedureContext, args: A) -> Ret; } @@ -226,7 +218,6 @@ impl IntoReducerResult for Result<(), E> { } } -#[cfg(feature = "unstable")] #[diagnostic::on_unimplemented( message = "The procedure return type `{Self}` does not implement `SpacetimeType`", note = "if you own the type, try adding `#[derive(SpacetimeType)]` to its definition" @@ -237,7 +228,6 @@ pub trait IntoProcedureResult: SpacetimeType + Serialize { bsatn::to_vec(&self).expect("Failed to serialize procedure result") } } -#[cfg(feature = "unstable")] impl IntoProcedureResult for T {} #[diagnostic::on_unimplemented( @@ -263,7 +253,6 @@ pub trait ReducerArg { } impl ReducerArg for T {} -#[cfg(feature = "unstable")] #[diagnostic::on_unimplemented( message = "the first argument of a procedure must be `&mut ProcedureContext`", label = "first argument must be `&mut ProcedureContext`" @@ -273,11 +262,9 @@ pub trait ProcedureContextArg { #[doc(hidden)] const _ITEM: () = (); } -#[cfg(feature = "unstable")] impl ProcedureContextArg for &mut ProcedureContext {} /// A trait of types that can be an argument of a procedure. -#[cfg(feature = "unstable")] #[diagnostic::on_unimplemented( message = "the procedure argument `{Self}` does not implement `SpacetimeType`", note = "if you own the type, try adding `#[derive(SpacetimeType)]` to its definition" @@ -287,7 +274,6 @@ pub trait ProcedureArg { #[doc(hidden)] const _ITEM: () = (); } -#[cfg(feature = "unstable")] impl ProcedureArg for T {} #[cfg(feature = "unstable")] @@ -484,7 +470,6 @@ pub struct FnKindReducer { _never: Infallible, } -#[cfg(feature = "unstable")] /// Tacit marker argument to [`ExportFunctionForScheduledTable`] for procedures. /// /// Holds the procedure's return type in order to avoid an error due to an unconstrained type argument. @@ -505,14 +490,7 @@ pub struct FnKindView { /// /// The `FnKind` parameter here is a coherence-defeating marker, which Will Crichton calls a "tacit parameter." /// See for details on this technique. -#[cfg_attr( - feature = "unstable", - doc = "It will be one of [`FnKindReducer`] or [`FnKindProcedure`] in modules that compile successfully." -)] -#[cfg_attr( - not(feature = "unstable"), - doc = "It will be [`FnKindReducer`] in modules that compile successfully." -)] +/// It will be one of [`FnKindReducer`] or [`FnKindProcedure`] in modules that compile successfully. /// /// It may be [`FnKindView`], but that will always fail to typecheck, as views cannot be used as scheduled functions. #[diagnostic::on_unimplemented( @@ -528,7 +506,6 @@ impl<'de, TableRow: SpacetimeType + Serialize + Deserialize<'de>, F: Reducer<'de { } -#[cfg(feature = "unstable")] impl< 'de, TableRow: SpacetimeType + Serialize + Deserialize<'de>, @@ -664,7 +641,6 @@ macro_rules! impl_reducer_procedure_view { } } - #[cfg(feature = "unstable")] impl<'de, Func, Ret, $($T: SpacetimeType + Deserialize<'de> + Serialize),*> Procedure<'de, ($($T,)*), Ret> for Func where Func: Fn(&mut ProcedureContext, $($T),*) -> Ret, @@ -829,7 +805,6 @@ pub fn register_reducer<'a, A: Args<'a>, I: FnInfo>(_: impl }) } -#[cfg(feature = "unstable")] pub fn register_procedure<'a, A, Ret, I>(_: impl Procedure<'a, A, Ret>) where A: Args<'a>, @@ -935,7 +910,6 @@ pub struct ModuleBuilder { /// The reducers of the module. reducers: Vec, /// The procedures of the module. - #[cfg(feature = "unstable")] procedures: Vec, /// The HTTP handlers of the module. #[cfg(feature = "unstable")] @@ -954,9 +928,7 @@ static DESCRIBERS: Mutex>> = Mutex::new(Vec::new()); pub type ReducerFn = fn(&ReducerContext, &[u8]) -> ReducerResult; static REDUCERS: OnceLock> = OnceLock::new(); -#[cfg(feature = "unstable")] pub type ProcedureFn = fn(&mut ProcedureContext, &[u8]) -> ProcedureResult; -#[cfg(feature = "unstable")] static PROCEDURES: OnceLock> = OnceLock::new(); #[cfg(feature = "unstable")] @@ -1002,7 +974,6 @@ extern "C" fn __describe_module__(description: BytesSink) { // Write the sets of reducers, procedures and views. REDUCERS.set(module.reducers).ok().unwrap(); - #[cfg(feature = "unstable")] PROCEDURES.set(module.procedures).ok().unwrap(); #[cfg(feature = "unstable")] HTTP_HANDLERS.set(module.http_handlers).ok().unwrap(); @@ -1141,7 +1112,6 @@ fn convert_err_to_errno(res: Result<(), Box>, out: BytesSink) -> i16 { /// the BSATN-serialized bytes of a value of the procedure's return type. /// /// Procedures always return the error 0. All other return values are reserved. -#[cfg(feature = "unstable")] #[unsafe(no_mangle)] extern "C" fn __call_procedure__( id: usize, diff --git a/docs/docs/00100-intro/00100-getting-started/00400-key-architecture.md b/docs/docs/00100-intro/00100-getting-started/00400-key-architecture.md index bb5201aeee5..61a70b681e7 100644 --- a/docs/docs/00100-intro/00100-getting-started/00400-key-architecture.md +++ b/docs/docs/00100-intro/00100-getting-started/00400-key-architecture.md @@ -316,8 +316,6 @@ Procedures can perform additional operations not possible in reducers, including However, procedures don't automatically run in database transactions, and must manually open and commit a transaction in order to read from or modify the database state. -Procedures are currently in beta, and their API may change in upcoming SpacetimeDB releases. - diff --git a/docs/docs/00100-intro/00100-getting-started/00500-faq.md b/docs/docs/00100-intro/00100-getting-started/00500-faq.md index 2552dd1b630..acbc7e5eb1e 100644 --- a/docs/docs/00100-intro/00100-getting-started/00500-faq.md +++ b/docs/docs/00100-intro/00100-getting-started/00500-faq.md @@ -90,7 +90,7 @@ Views are read-only functions that compute derived data from your tables. They a ### What are procedures? -Procedures are similar to reducers but with additional capabilities. They can make HTTP requests to external services and manually manage transactions. Clients can also call procedures over HTTP. Procedures are currently in beta. Use reducers for most cases; use procedures when you need to interact with the outside world. In the future, procedures will be configurable as HTTP endpoints. See [Procedures](../../00200-core-concepts/00200-functions/00400-procedures.md) for details. +Procedures are similar to reducers but with additional capabilities. They can make HTTP requests to external services and manually manage transactions. Clients can also call procedures over HTTP. Use reducers for most cases; use procedures when you need to interact with the outside world. In the future, procedures will be configurable as HTTP endpoints. See [Procedures](../../00200-core-concepts/00200-functions/00400-procedures.md) for details. --- diff --git a/docs/docs/00200-core-concepts/00200-functions.md b/docs/docs/00200-core-concepts/00200-functions.md index 11e4eb533b2..6af1a1956fb 100644 --- a/docs/docs/00200-core-concepts/00200-functions.md +++ b/docs/docs/00200-core-concepts/00200-functions.md @@ -28,7 +28,7 @@ Reducers are isolated and cannot interact with the outside world - they can only **[Procedures](./00200-functions/00400-procedures.md)** are functions similar to reducers, but with the ability to perform operations beyond the database. Unlike reducers, procedures can make HTTP requests to external services. However, procedures don't automatically run in database transactions - they must manually open and commit transactions to read from or modify database state. -Procedures are currently in beta and should only be used when you need their special capabilities, such as making HTTP requests. For standard database operations, prefer using reducers. +Procedures should only be used when you need their special capabilities, such as making HTTP requests. For standard database operations, prefer using reducers. ## Views diff --git a/docs/docs/00200-core-concepts/00200-functions/00400-procedures.md b/docs/docs/00200-core-concepts/00200-functions/00400-procedures.md index 5149aa7e6c3..32589a22a88 100644 --- a/docs/docs/00200-core-concepts/00200-functions/00400-procedures.md +++ b/docs/docs/00200-core-concepts/00200-functions/00400-procedures.md @@ -15,10 +15,6 @@ However, procedures don't automatically run in database transactions, and must manually open and commit a transaction in order to read from or modify the database state. For this reason, prefer defining reducers rather than procedures unless you need to use one of the special procedure operators. -:::warning -***Procedures are currently in beta, and their API may change in upcoming SpacetimeDB releases.*** -::: - ## Defining Procedures diff --git a/docs/docs/00200-core-concepts/00600-clients.md b/docs/docs/00200-core-concepts/00600-clients.md index e149b3b63a0..011a84cc29a 100644 --- a/docs/docs/00200-core-concepts/00600-clients.md +++ b/docs/docs/00200-core-concepts/00600-clients.md @@ -48,7 +48,7 @@ Clients receive automatic updates when subscribed data changes. The SDKs provide Clients can invoke server-side functions to modify data or perform operations: - **[Reducers](./00200-functions/00300-reducers/00300-reducers.md)** - Transactional functions that modify database state -- **[Procedures](./00200-functions/00400-procedures.md)** - Functions that can perform external operations like HTTP requests (beta) +- **[Procedures](./00200-functions/00400-procedures.md)** - Functions that can perform external operations like HTTP requests ### Type Safety diff --git a/docs/docs/00200-core-concepts/00600-clients/00200-codegen.md b/docs/docs/00200-core-concepts/00600-clients/00200-codegen.md index 9d9e537d66d..4885340cca5 100644 --- a/docs/docs/00200-core-concepts/00600-clients/00200-codegen.md +++ b/docs/docs/00200-core-concepts/00600-clients/00200-codegen.md @@ -257,7 +257,7 @@ For each [procedure](../00200-functions/00400-procedures.md) in your module, cod - **Return value handling** for procedures that return results - **Type-safe parameters** matching the procedure's signature -Procedures are currently in beta. For example, a `fetch_external_data` procedure becomes: +For example, a `fetch_external_data` procedure becomes: diff --git a/docs/static/llms.md b/docs/static/llms.md index 2f17b8fd21a..e0d0b97b4f2 100644 --- a/docs/static/llms.md +++ b/docs/static/llms.md @@ -50,6 +50,7 @@ This section covers the fundamental concepts you need to understand to build app - [Configuring your project](/docs/core-concepts/authentication/spacetimeauth/configuring-a-project): SpacetimeAuth is currently in beta, some features may not be available yet or may change in the future. You might encounter bugs or issues while using the service. Please report any problems you encounter to help us improve SpacetimeAuth. - [Creating a project](/docs/core-concepts/authentication/spacetimeauth/creating-a-project): SpacetimeAuth is currently in beta, some features may not be available yet or may change in the future. You might encounter bugs or issues while using the service. Please report any problems you encounter to help us improve SpacetimeAuth. - [React Integration](/docs/core-concepts/authentication/spacetimeauth/react-integration): SpacetimeAuth is currently in beta, some features may not be available yet or may change in the future. You might encounter bugs or issues while using the service. Please report any problems you encounter to help us improve SpacetimeAuth. +- [Steam Session Ticket Authentication](/docs/core-concepts/authentication/spacetimeauth/steam): SpacetimeAuth supports authentication using Steam's Session Ticket system. This allows - [Testing](/docs/core-concepts/authentication/spacetimeauth/testing): SpacetimeAuth is currently in beta, some features may not be available yet or may change in the future. You might encounter bugs or issues while using the service. Please report any problems you encounter to help us improve SpacetimeAuth. - [Using Auth Claims](/docs/core-concepts/authentication/usage): SpacetimeDB allows you to easily access authentication (auth) claims embedded in @@ -70,6 +71,7 @@ A module is a collection of functions and schema definitions, which can be writt | Property / Characteristic | Reducers | Procedures | Views | - [Functions](/docs/functions): | Property / Characteristic | Reducers | Procedures | Views | +- [HTTP Handlers](/docs/functions/http-handlers): HTTP handlers allow a SpacetimeDB database to expose an HTTP API. - [Procedures](/docs/functions/procedures): A procedure is a function exported by a database, similar to a reducer. - [Overview](/docs/functions/reducers): Reducers are functions that modify database state in response to client requests or system events. They are the only way to mutate tables in SpacetimeDB - all database changes must go through reducers. - [Error Handling](/docs/functions/reducers/error-handling): Error Handling @@ -80,6 +82,7 @@ A module is a collection of functions and schema definitions, which can be writt ### how-to - [Maincloud](/docs/how-to/deploy/maincloud): Maincloud is SpacetimeDB's fully managed serverless platform. It handles infrastructure, scaling, replication, and backups so you can focus on building your application. Maincloud scales to zero when your database is idle, so you only pay for what you use. +- [Railway](/docs/how-to/deploy/railway): Railway is a hosted platform for deploying infrastructure and application services. If you want to run SpacetimeDB without managing your own VM, the official Railway template is a quick way to get started. - [Self-hosting](/docs/how-to/deploy/self-hosting): This tutorial will guide you through setting up SpacetimeDB on an Ubuntu 24.04 server, securing it with HTTPS using Nginx and Let's Encrypt, and configuring a systemd service to keep it running. - [Logging](/docs/how-to/logging): SpacetimeDB provides logging capabilities for debugging and monitoring your modules. Log messages are private to the database owner and are not visible to clients. - [PostgreSQL Wire Protocol (PGWire)](/docs/how-to/pg-wire): SpacetimeDB supports the PostgreSQL wire protocol (PGWire), @@ -90,7 +93,7 @@ A module is a collection of functions and schema definitions, which can be writt ### http - [Authorization](/docs/http/authorization): Generating identities and tokens -- [/v1/database](/docs/http/database): The HTTP endpoints in /v1/database allow clients to interact with Spacetime databases in a variety of ways, including retrieving information, creating and deleting databases, invoking reducers and evaluating SQL queries. +- [/v1/database](/docs/http/database): The HTTP endpoints in /v1/database allow clients to interact with Spacetime databases in a variety of ways, including retrieving information, creating and deleting databases, invoking reducers and evaluating SQL queries. These APIs are intended primarily for management, debugging and interactive developer use, and have not been optimized for performance to the same extent as the WebSocket API used by the SpacetimeDB client SDKs. - [/v1/identity](/docs/http/identity): The HTTP endpoints in /v1/identity allow clients to generate and manage Spacetime public identities and private tokens. ### intro @@ -104,6 +107,7 @@ A module is a collection of functions and schema definitions, which can be writt ### quickstarts - [Angular Quickstart](/docs/quickstarts/angular): Get a SpacetimeDB Angular app running in under 5 minutes. +- [Astro Quickstart](/docs/quickstarts/astro): Get a SpacetimeDB Astro app running in under 5 minutes. - [Browser Quickstart](/docs/quickstarts/browser): Get a SpacetimeDB app running in the browser with inline JavaScript. - [Bun Quickstart](/docs/quickstarts/bun): Get a SpacetimeDB Bun app running in under 5 minutes. - [C++ Quickstart](/docs/quickstarts/c-plus-plus): Get a SpacetimeDB C++ app running in under 5 minutes. @@ -122,6 +126,7 @@ A module is a collection of functions and schema definitions, which can be writt ### reference +- [Commitlog](/docs/reference/internals/commitlog): The commitlog is the write-ahead log (WAL) used by SpacetimeDB to persist all committed transactions. As an in-memory database, SpacetimeDB relies entirely on this log for durability. Every committed transaction is written to the commitlog before it is considered durable, and the full state of any database can be reconstructed by replaying the log from the beginning. - [SQL Reference](/docs/reference/sql): SpacetimeDB supports two subsets of SQL: ### resources @@ -152,9 +157,20 @@ Tables are the way to store data in SpacetimeDB. All data in SpacetimeDB is stor - [Performance Best Practices](/docs/tables/performance): Follow these guidelines to optimize table performance in your SpacetimeDB modules. - [Schedule Tables](/docs/tables/schedule-tables): Tables can trigger reducers or procedures at specific times by including a special scheduling column. This allows you to schedule future actions like sending reminders, expiring items, or running periodic maintenance tasks. +### troubleshooting + +This is a list of common problems when using SpacetimeDB and how to fix them. + +- [Troubleshooting](/docs/troubleshooting): This is a list of common problems when using SpacetimeDB and how to fix them. + ### tutorials - [Chat App Tutorial](/docs/tutorials/chat-app): In this tutorial, we'll implement a simple chat server as a SpacetimeDB module. You can write your module in TypeScript, C#, or Rust - use the tabs throughout this guide to see code examples in your preferred language. +- [Godot Tutorial](/docs/tutorials/godot): Need help with the tutorial or CLI commands? Join our Discord server! +- [1 - Setup](/docs/tutorials/godot/part-1): Unity Tutorial Hero Image +- [2 - Connecting to SpacetimeDB](/docs/tutorials/godot/part-2): Need help with the tutorial? Join our Discord server! +- [3 - Gameplay](/docs/tutorials/Godot/part-3): Need help with the tutorial? Join our Discord server! +- [4 - Moving and Colliding](/docs/tutorials/Godot/part-4): Need help with the tutorial? Join our Discord server! - [Unity Tutorial](/docs/tutorials/unity): Need help with the tutorial or CLI commands? Join our Discord server! - [1 - Setup](/docs/tutorials/unity/part-1): Unity Tutorial Hero Image - [2 - Connecting to SpacetimeDB](/docs/tutorials/unity/part-2): Need help with the tutorial? Join our Discord server! diff --git a/modules/sdk-test-procedure/Cargo.toml b/modules/sdk-test-procedure/Cargo.toml index 6e143334e10..b17e8f9b3c1 100644 --- a/modules/sdk-test-procedure/Cargo.toml +++ b/modules/sdk-test-procedure/Cargo.toml @@ -16,4 +16,3 @@ paste.workspace = true [dependencies.spacetimedb] workspace = true -features = ["unstable"] From 59ddb6654a032b467c76820100505a800c060f92 Mon Sep 17 00:00:00 2001 From: Tyler Cloutier Date: Mon, 1 Jun 2026 19:54:27 -0400 Subject: [PATCH 2/3] Fix lints: rustfmt import order, doc link, gate handler wire tests - rustfmt: reorder the split `use` statements in http.rs/rng.rs/rt.rs. - cargo doc: fix a pre-existing broken intra-doc link in HttpClient::send (`http::request::Builder::extension`), newly surfaced now that the outgoing HTTP client is documented in the default (non-unstable) build. - clippy: gate the request_from_wire/response_into_wire test module behind `unstable`, since those functions are now gated. --- crates/bindings/src/http.rs | 10 +++++----- crates/bindings/src/rng.rs | 2 +- crates/bindings/src/rt.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/bindings/src/http.rs b/crates/bindings/src/http.rs index bf6b18eae2c..ec476bba46e 100644 --- a/crates/bindings/src/http.rs +++ b/crates/bindings/src/http.rs @@ -8,10 +8,10 @@ use crate::rt::{read_bytes_source_as, read_bytes_source_into}; use crate::IterBuf; // Imports used only by the (still-unstable) HTTP handler machinery. -#[cfg(feature = "unstable")] -use crate::{try_with_tx, with_tx, Timestamp, TxContext}; #[cfg(all(feature = "unstable", feature = "rand08"))] use crate::StdbRng; +#[cfg(feature = "unstable")] +use crate::{try_with_tx, with_tx, Timestamp, TxContext}; use bytes::Bytes; #[cfg(all(feature = "rand", feature = "unstable"))] use rand08::RngCore; @@ -20,11 +20,11 @@ use spacetimedb_lib::db::raw_def::v10::MethodOrAny; use spacetimedb_lib::http as st_http; #[cfg(feature = "unstable")] use spacetimedb_lib::http::{character_is_acceptable_for_route_path, ACCEPTABLE_ROUTE_PATH_CHARS_HUMAN_DESCRIPTION}; -use spacetimedb_lib::{bsatn, TimeDuration}; #[cfg(feature = "unstable")] use spacetimedb_lib::Identity; #[cfg(all(feature = "unstable", feature = "rand"))] use spacetimedb_lib::Uuid; +use spacetimedb_lib::{bsatn, TimeDuration}; #[cfg(all(feature = "unstable", feature = "rand"))] use std::cell::Cell; #[cfg(all(feature = "unstable", feature = "rand08"))] @@ -432,7 +432,7 @@ impl HttpClient { /// /// For simple `GET` requests with no headers, use [`HttpClient::get`] instead. /// - /// Include a [`Timeout`] in the [`Request::extensions`] via [`http::request::RequestBuilder::extension`] + /// Include a [`Timeout`] in the [`Request::extensions`] via [`http::request::Builder::extension`] /// to impose a timeout on the request. /// All HTTP requests in SpacetimeDB are subject to a maximum timeout of 500 milliseconds. /// All other extensions in `request` are ignored. @@ -810,7 +810,7 @@ impl From for Error { } } -#[cfg(test)] +#[cfg(all(test, feature = "unstable"))] mod tests { use super::*; diff --git a/crates/bindings/src/rng.rs b/crates/bindings/src/rng.rs index a883030e43e..2e543108d32 100644 --- a/crates/bindings/src/rng.rs +++ b/crates/bindings/src/rng.rs @@ -1,6 +1,6 @@ -use crate::ProcedureContext; #[cfg(feature = "unstable")] use crate::http::HandlerContext; +use crate::ProcedureContext; use crate::{rand, ReducerContext}; use core::cell::UnsafeCell; use core::marker::PhantomData; diff --git a/crates/bindings/src/rt.rs b/crates/bindings/src/rt.rs index 29c0c833d8c..e566b21efb8 100644 --- a/crates/bindings/src/rt.rs +++ b/crates/bindings/src/rt.rs @@ -21,9 +21,9 @@ use std::marker::PhantomData; use std::sync::{Mutex, OnceLock}; pub use sys::raw::{BytesSink, BytesSource}; -use crate::{ProcedureContext, ProcedureResult}; #[cfg(feature = "unstable")] use crate::http::{self, HandlerContext}; +use crate::{ProcedureContext, ProcedureResult}; pub trait IntoVec { fn into_vec(self) -> Vec; From 4caab7543f0a5b74bbba800eab895cb580a6f2c0 Mon Sep 17 00:00:00 2001 From: Tyler Cloutier Date: Mon, 1 Jun 2026 20:13:17 -0400 Subject: [PATCH 3/3] Fix rustdoc broken links in bindings-sys procedure module The procedure module is now documented in the default (non-unstable) `cargo doc` build, surfacing three unresolved [`Errno`] intra-doc links. Qualify them as [`crate::Errno`] so they resolve from within the submodule. --- crates/bindings-sys/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bindings-sys/src/lib.rs b/crates/bindings-sys/src/lib.rs index 566b2079ebb..0295b4616e5 100644 --- a/crates/bindings-sys/src/lib.rs +++ b/crates/bindings-sys/src/lib.rs @@ -1562,7 +1562,7 @@ pub mod procedure { /// /// Once complete, returns `Ok(timestamp)` on success, /// enabling further calls that require a pending transaction, - /// or [`Errno`] otherwise. + /// or [`crate::Errno`] otherwise. /// /// # Errors /// @@ -1578,7 +1578,7 @@ pub mod procedure { /// blocking until the transaction has been committed /// and subscription queries have been run and broadcast. /// - /// Once complete, returns `Ok(())` on success, or an [`Errno`] otherwise. + /// Once complete, returns `Ok(())` on success, or an [`crate::Errno`] otherwise. /// /// # Errors /// @@ -1600,7 +1600,7 @@ pub mod procedure { /// Aborts a mutable transaction, /// blocking until the transaction has been rolled back. /// - /// Once complete, returns `Ok(())` on success, or an [`Errno`] otherwise. + /// Once complete, returns `Ok(())` on success, or an [`crate::Errno`] otherwise. /// /// # Errors ///