202 Commits

Author SHA1 Message Date
Luke c7af2d4cd3 Deprecate ReducerContext::identity in favor of database_identity (#4843)
## 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
2026-05-04 19:50:39 +00:00
Kilian Strunz 309cf55604 [Rust] Add possibility to be generic over DbContext (#4707)
# Description of Changes

This patch aims to improve the situation for the need of a generic
function over multiple `ctxs`.
The `DbContext` was introduced for this but due to the associated type
amibguity when trying to implement it another mmethod is needed.

This pr implements a `db_read_only()` method which always results in a
`LocalReadOnly` hence Rust can infer the types of a the returned type
(which prior to this was either `__view , __query and a 3rd one i cent
remember right now 😓`.

I have chosen to be defensive by implementing it as `unstable` but i can
also remove this if that is desired.

It allows the following pattern which has been workig great in my
project so its time to contribute it :>

```rust
pub(crate) trait YourTableNameRead {
   // Your methods which only need read access
  fn test(&self,args);

}

// The read version is a supertrait to give access to the read methods.
pub(crate) trait YourTableNameWrite: YourTableNameRead {
  // Your methods which need read-write access
}

// The read version gets implemented for every DbContext since we can always read.
impl<Db: DbContext> YourTableNameRead for Db {
  fn test(&self,args) {
   self.db_read_only().table_name().whatever(args);
}

// By constraining the associated type to Local we only get this for writeable ctxs.
impl<Db: DbContext<DbView = Local>> YourTableNameWrite for Db {}

```

These allow you to do on the calling site:
```rust
use YourTableNameRead;

#[view|reducer|procedure]
fn my_func(ctx: Reducer|(Anon)View|Tx, args ) {
   ctx.test(args);
}
```



# API and ABI breaking changes

None

# Expected complexity level and risk

1. Minor api and qol adition which is furthermore unstable.

# Testing

- [x] Works in my project

---------

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-05-04 18:46:47 +00:00
Rafael Guerreiro a8c8252a0b Make Timestamp a FilterableValue (#4693)
# Description of Changes
Make Timestamp a FilterableValue in Rust, C#, and Typescript. I'm not
sure this is changing all the places because we have the server and the
client in those 3 languages.

# API and ABI breaking changes
It's an additive change.

# Expected complexity level and risk
3. There are some designs decisions, like comparing timestamp to
strings/numbers.

# Testing
Added unit tests for the 3 languages.
2026-04-28 22:06:44 +00:00
miXin b150cf6473 align UUID reducer examples with allowed signatures (#3999)
# Description of Changes

- Corrected UUID v4/v7 reducer documentation examples to use valid
reducer signatures returning ()/Result<(), E>

# API and ABI breaking changes

- None

# Expected complexity level and risk

- 1 (doc example corrections only)

# Testing

- [ ] Not run (docs-only change)
- [ ] Please review documentation formatting and correctness

---------

Signed-off-by: miXin <52082254@qq.com>
Co-authored-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
2026-04-27 18:00:14 +00:00
Zeke Foppa 70db721c3a Revert breaking PRs (#4881)
# Description of Changes

Revert the following PRs that have caused some breakage:
```
a32cffa76 Finish refactoring out replay (#4850)
d639be0af Replay: some code motion & reuse `ReplayCommittedState` (#4849)
78d6b6f7d Update NativeAOT-LLVM infrastructure to current ABI (#4515)
d5c1738c1 Better module backtraces for panics and whatnot (#577)
6f23b19f3 Wait for database update to become durable (#4846)
81c9eab86 Add `spacetime lock/unlock` to prevent accidental database deletion (#4502)
809aebd7c Move field `replay_table_updated` to `ReplayCommittedState` (#4807)
21b58ef99 Update axum (#2713)
b5cadff7a Extract replay stuff out of `CommittedState`, part 1 (#4804)
```

I also updated the Python smoketests for breakage introduced in
https://github.com/clockworklabs/SpacetimeDB/pull/4502. Reverting that
PR caused conflicts, so this fix is more straightforward.

# API and ABI breaking changes

Maybe kind of, but we haven't released any of these.

# Expected complexity level and risk

1

# Testing

Ask @bfops about testing

---------

Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2026-04-23 14:54:23 -07:00
Mazdak Farrokhzad adbe22b556 bindings: reuse panic message for datastore_index_scan_point_bsatn (#4876)
# Description of Changes

See tin.

# API and ABI breaking changes

None

# Expected complexity level and risk

1

# Testing

Covered by existing tests.
2026-04-23 12:49:17 +00:00
Noa d5c1738c15 Better module backtraces for panics and whatnot (#577)
# Description of Changes


![image](https://github.com/clockworklabs/SpacetimeDB/assets/33094578/9c6356af-9b34-462a-8441-8bd859a73b86)

If these symbols aren't in the stack, it does no processing

# Expected complexity level and risk

1 - it's pretty self-contained, and backwards-compatible with the
existing logs data format

---------

Co-authored-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-04-21 13:08:57 +00:00
Mazdak Farrokhzad 18f6da6794 Add module ABI & API for clearing tables (#4729)
# Description of Changes

Support is added to Rust, C#, C++, and TS modules.

# API and ABI breaking changes

None

# Expected complexity level and risk

1

# Testing

I wasn't able to regen module bindings for sdk tests, hitting an error
while doing so.

---------

Co-authored-by: Jason Larabie <jason@clockworklabs.io>
2026-04-09 21:04:33 +00:00
Mazdak Farrokhzad 52872521d4 add Deserialize::validate for non-allocating validation (#4493)
# Description of Changes

Adds `Deserialize::validate` and all the friends necessary to make that
work.
The point of this is to enable allocation-less validation of input in
some data format, in particular BSATN, against some expected type, in
particular an `AlgebraicValue` at an `AlgebraicType`.
This is extracted from
https://github.com/clockworklabs/SpacetimeDB/pull/4311 and is used there
to convert raw BSATN to `BytesKey` without constructing the composite
`AlgebraicValue` just for validation only to throw it away immediately.

# API and ABI breaking changes

None

# Expected complexity level and risk

2

# Testing

TODO: tweak existing SATS roundtrip tests to also check validation.

---------

Co-authored-by: Noa <coolreader18@gmail.com>
2026-03-19 20:29:59 +00:00
Kilian Strunz 7a2652ea61 Allow obtaining a AnonymousViewContext from a ViewContext (#4671)
# Description of Changes

Title.
Is useful to more easily reuse code.
I asked @joshua-spacetime on discord if this would be reasonable and he
said 👍 .
This mirrors the method available on `ReducerContext` for consistency.

# API and ABI breaking changes

None

# Expected complexity level and risk

1 - minimal api surface addition

# Testing

- [x] Tested in my project and works as expected.

---------

Signed-off-by: joshua-spacetime <josh@clockworklabs.io>
Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
2026-03-19 17:14:30 +00:00
joshua-spacetime 3fe50e72d0 [Rust] Extend view table accessors with count (#4638)
# Description of Changes

Adds `count` to rust's procedural view API.

This API already existed in C# and typescript. This patch just adds
tests for those module languages.

We were already tracking reads for `count`, and so all this patch does
is add the new rust module bindings.

# API and ABI breaking changes

None

# Expected complexity level and risk

1

# Testing

Smoketests for rust, C#, and typescript.
2026-03-16 13:03:50 +00:00
joshua-spacetime 6eaf06b6b5 [Rust] Primary keys for query builder views (#4572)
# Description of Changes

Query builder views return a subset of rows from a physical table. If
that table has a primary key, then so should the view. What this means
concretely is that the view should expose the same api as the table,
specifically as it relates to the primary key column.

With that in mind, this patch commits the following changes:
1. Annotates `ViewDef` with a `primary_key`
2. Updates the return type of query builder views in the raw module def
to a special product type
3. Adds an index for the primary key on the view's backing table
4. Updates the query planner to use this index
5. Updates rust client codegen to generate `on_update` for such views

# API and ABI breaking changes

None

Old `impl Query` views compiled with an older version of SpacetimeDB
will continue to work as they did before - without a primary key.

# Expected complexity level and risk

3

# Testing

- [x] New rust sdk integration suite exercising `on_update` for PK views
and semijoin scenarios
- [x] Smoketests for PK views and semijoin scenarios
2026-03-11 13:00:43 +00:00
Zeke Foppa 6d9cf691f2 CI - rustfmt instead of cargo fmt (#4595)
# Description of Changes

`cargo ci lint` was running `cargo fmt`, but that didn't pick up all
files. As a result, our pre-commit hook (which just runs `rustfmt` on
any changed `.rs` files) would change otherwise-untouched files in merge
commits.

This PR addresses that discrepancy by having `cargo ci lint` run
`rustfmt` on all tracked `.rs` files.

The entire diff is just `rustfmt` changes except for the changes in
`tools/ci/src/main.rs`.

# API and ABI breaking changes

<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->

# Expected complexity level and risk

2

# Testing

- [x] `cargo ci lint` fails
- [x] `cargo ci lint` passes after running `rustfmt` on everything
- [x] `cargo fmt --all` doesn't cause any diff after doing the above

---------

Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2026-03-10 05:58:54 +00:00
Shiven Garia af6d0df06c Fix typos in comments and doc comments across crates (#4560)
## Summary
- Fix `Deerialize` → `Deserialize` in doc comments for `ser.rs` and
`typespace.rs` (these are in developer-facing trait documentation)
- Fix `thier` → `their`, `reinintializes` → `reinitializes`, `occurence`
→ `occurrence`, `secion` → `section` across 4 other crates

## Details
Six typo fixes across 6 files, no logic changes:

| File | Typo | Fix |
|------|------|-----|
| `crates/sats/src/ser.rs:280` | `Deerialize` | `Deserialize` |
| `crates/sats/src/typespace.rs:303` | `Deerialize` | `Deserialize` |
| `crates/table/src/table.rs:460` | `thier` | `their` |
| `crates/schema/tests/ensure_same_schema.rs:21` | `reinintializes` |
`reinitializes` |
| `crates/lib/src/http.rs:131` | `occurence` | `occurrence` |
| `crates/bindings/src/lib.rs:763` | `secion` | `section` |

## Test plan
- [ ] No logic changes — comments and doc comments only
- [ ] CI should pass without issues

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 20:12:38 +00:00
Noa e3582131fe Migrate to Rust 2024 (#3802)
# Description of Changes

It'd be best to review this commit-by-commit, and using
[difftastic](https://difftastic.wilfred.me.uk) to easily tell when
changes are minor in terms of syntax but a line based diff doesn't show
that.

# Expected complexity level and risk

3 - edition2024 does bring changes to drop order, which could cause
issues with locks, but I looked through [all of the warnings that
weren't fixed
automatically](https://gistcdn.githack.com/coolreader18/80485ae5c5f82de1784229cce2febb26/raw/ba80f3fecda66ceb34f4f7ad73b98ea02d4893a2/warnings.html)
and couldn't find any issues.

# Testing

n/a; internal code change
2026-03-03 11:06:52 +00:00
Ludv1gL d2223a2237 fix: Handle empty HTTP response body in procedure bindings (#4386)
## Summary

- `create_bytes_source()` in the host returns `BytesSourceId::INVALID`
for empty response bodies, but `HttpClient::send()` unconditionally
reads the body source via `read_bytes_source_into()`, which panics with
`"invalid source passed"`
- Any procedure HTTP request returning an empty body (e.g. HTTP 200 with
no content from a successful reducer call) triggers this panic
- Fix: check for `BytesSource::INVALID` before reading, matching the
existing pattern used for JWT payloads in `bindings-sys`

## Test plan

- [x] Verified `cargo check -p spacetimedb` passes
- [x] Trigger an HTTP request from a procedure that returns an empty
response body (e.g. calling a reducer via HTTP that returns 200 with no
body)
- [x] Verify no panic occurs and an empty `Body` is returned

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-02-21 04:54:16 +00:00
clockwork-labs-bot a89634b4a5 Add #[spacetimedb::settings] for module-level configuration (#4366)
## Summary

Adds a cross-language `#[spacetimedb::settings]` mechanism for declaring
module-level settings. The first supported setting is
`CASE_CONVERSION_POLICY`, which controls how identifiers are
case-converted.

### Rust

```rust
use spacetimedb::CaseConversionPolicy;

#[spacetimedb::settings]
const CASE_CONVERSION_POLICY: CaseConversionPolicy = CaseConversionPolicy::None;
```

- Proc macro validates const name against `KNOWN_SETTINGS`
- Generates `__preinit__` export for registration
- Duplicate settings produce a linker error (duplicate symbol)

### TypeScript

```ts
export const moduleSettings: ModuleSettings = {
  caseConversionPolicy: CaseConversionPolicy.None,
};
```

- `ModuleSettings` interface with typed fields
- `caseConversionPolicy` section pushed in `rawModuleDefV10()`


## Stacked on

- `shub/case-conversion` (base)
- PR #4364 (internal opt-out API)

This PR adds the proper user-facing API on top of the internal mechanism
in #4364.

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-02-20 15:26:40 +00:00
Shubham Mishra e2f8a60759 Case conversion (#4263)
# Description of Changes

Update the Default casing policy to `snake_case` for `RawModuleDefV10`.

Messy PR contains changes at different places, so that CI can pass:

Here are the main changes as follows:
- `bindings-macro` & `bindings` crate: `name` macro in Indexes for
canonical name and supply it to `RawModuleDefV10` via `ExplicitNames`.
- `bindings-typescript`: 
- Changes has been reviewed through this PR -
https://github.com/clockworklabs/SpacetimeDB/pull/4308.
   
- `binding-csharp`: a single line change to pass `sourceName` of index
instead of null.
- `codegen`:
  
- Changes has been merged from branch -
https://github.com/clockworklabs/SpacetimeDB/pull/4337.
  
- Except a fix in rust codegen to use canonical name in Query buillder
instead of accessor.
  
- `lib/db/raw_def`: Extends `RawDefModuleV10` structure to support case
conversion.
  
- `schema` crate:
- `validate/v9` - Nothing itself should change or changes in v9
validation logic but the file contains a `CoreValidator` which is shared
with `validate/v10`. No test have t be updated to `validate/v9` which
ensures we aren't regressing it.
- `validate/v10`: This is the main meat, look at the new tests added in
bottom to understand what it does.
     
   -  Rest of the files are either test updates or module bindings. 
     
    ## Testing:
1. Extensive unit tests have been added to verify generated `ModuleDef`
is correct.
2. I have done some e2e testing to verify rust codegen with rust and
typescript modules.
3. I would have like to do more testing for other codegens , I am
continue doing .

I have removed `sql.py` smoketest, as that seems to be already migated
in new framework and was headache to update.

## Expected complexity level and risk
4, It could have side-effect which aren't easily visible.


 
 
 
 
 
 -  -  -

---------

Signed-off-by: Shubham Mishra <shivam828787@gmail.com>
Co-authored-by: rekhoff <r.ekhoff@clockworklabs.io>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <bot@clockworklabs.com>
Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
Co-authored-by: Noa <coolreader18@gmail.com>
Co-authored-by: = <cloutiertyler@gmail.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@clockworklabs.io>
Co-authored-by: Jason Larabie <jason@clockworklabs.io>
Co-authored-by: Phoebe Goldman <phoebe@clockworklabs.io>
2026-02-20 10:44:29 +00:00
Jason Larabie 0590ab00f8 Rust docs updated for name to accessor (#4344)
# Description of Changes

- Updated all markdown files that call out `#[spacetimedb::table(name`
to `#[spacetimedb::table(accessor`
- Updated the LLM details on the same change

# API and ABI breaking changes

N/A

# Expected complexity level and risk

1 - Small rework in documentation to use the new 

# Testing

- [x] Did a small double check on name vs accessor locally
- [x] Codex tested all the LLM answers
2026-02-18 23:06:09 +00:00
Shubham Mishra e4098f98d9 Rust: macro change name -> accessor (#4264)
## Description of Changes

This PR primarily affects the `bindings-macro` and `schema` crates to
review:

### Core changes

1. Replaces the `name` macro with `accessor` for **Tables, Views,
Procedures, and Reducers** in Rust modules.
2. Extends `RawModuleDefV10` with a new section for:

   * case conversion policies
   * explicit names
    New sections are not validated in this PR so not functional.
3. Updates index behavior:

* Index names are now always **system-generated** for clients. Which
will be fixed in follow-up PR when we start validating RawModuleDef with
explicit names.
   * The `accessor` name for an index is used only inside the module.


## Breaking changes (API/ABI)

1. **Rust modules**

   * The `name` macro must be replaced with `accessor`.

2. **Client bindings (all languages)**

* Index names are now system-generated instead of using explicitly
provided names.


**Complexity:** 3

A follow-up PR will reintroduce explicit names with support for case
conversion.

---------

Co-authored-by: rekhoff <r.ekhoff@clockworklabs.io>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <bot@clockworklabs.com>
2026-02-16 15:23:50 +00:00
Tyler Cloutier 3f58b5951b Implement event tables (server, Rust/TS/C# codegen + client SDKs) (#4217)
## Summary

Implements event tables end-to-end: server datastore, module bindings
(Rust/TypeScript/C#), client codegen (Rust/TypeScript/C#), client SDKs
(Rust/TypeScript/C#), and integration tests.

Event tables are tables whose rows are ephemeral — they persist to the
commitlog and are delivered to V2 subscribers, but are NOT merged into
committed state. Rows are only visible within the transaction that
inserted them. This is the mechanism that replaces reducer event
callbacks in 2.0.

## What's included

### Server
- `is_event` flag on `RawTableDefV10`, `TableDef`, `TableSchema`
- Event table rows recorded in TxData but skipped during committed state
merge
- Commitlog replay treats event table inserts as no-ops
- Migration validation rejects changing `is_event` between module
versions
- `SELECT * FROM *` excludes event tables
- V1 WebSocket subscriptions to event tables rejected with upgrade
message
- V2 subscription path delivers event table rows correctly
- `CanBeLookupTable` trait — event tables cannot be lookup tables in
semijoins
- Runtime view validation rejects event tables

### Module bindings
- **Rust**: `#[spacetimedb::table(name = my_events, public, event)]`
- **TypeScript**: `table({ event: true }, ...)`
- **C#**: `[Table(Event = true)]`

### Client codegen (`crates/codegen/`)
- **Rust**: Generates `EventTable` impl (insert-only) for event tables,
`Table` impl for normal tables. `CanBeLookupTable` emitted for non-event
tables.
- **TypeScript**: Emits `event: true` in generated table schemas.
`ClientTableCore` type excludes `onDelete`/`onUpdate` for event tables
via conditional types.
- **C#**: Generates classes inheriting from `RemoteEventTableHandle`
(which hides `OnDelete`/`OnBeforeDelete`/`OnUpdate`) for event tables.

### Client SDKs
- **Rust**: `EventTable` trait with insert-only callbacks, client cache
bypass, `count()` returns 0, `iter()` returns empty
- **TypeScript**: Event table cache bypass in `table_cache.ts` — fires
`onInsert` callbacks but doesn't store rows. Type-level narrowing
excludes delete/update methods.
- **C#**: `RemoteEventTableHandle` base class hides delete/update
events. Parse/Apply/PostApply handle `EventTableRows` wire format, skip
cache storage, fire only `OnInsert`.

### Tests
- 9 datastore unit tests (insert/delete/update semantics, replay,
constraints, indexes, auto-inc, cross-tx reset)
- 3 Rust SDK integration tests (basic events, multiple events per
reducer, no persistence across transactions)
- Codegen snapshot tests (Rust, TypeScript, C#)
- Trybuild compile tests (event tables rejected as semijoin lookup
tables)

## Deferred
- `on_delete` codegen for event tables (server only sends inserts;
client synthesis deferred)
- Event tables in subscription joins / views (well-defined but
restricted for now)
- C++ SDK support
- RLS integration test

## API and ABI breaking changes

- `is_event: bool` added to `RawTableDefV10` (appended, defaults to
`false` — existing modules unaffected)
- `CanBeLookupTable` trait bound on semijoin methods in query builder
(all non-event tables implement it, so existing code compiles unchanged)
- `RemoteEventTableHandle` added to C# SDK (new base class for generated
event table handles)

## Expected complexity level and risk

3 — Changes touch the schema pipeline end-to-end and all three client
SDKs, but each individual change is straightforward. The core risk area
is the committed state merge skip in `committed_state.rs`. Client SDK
changes are additive (new code paths for event tables, existing paths
unchanged).

## Testing

- [x] `cargo clippy --workspace --tests --benches` passes
- [x] `cargo test -p spacetimedb-codegen` (snapshot tests)
- [x] `cargo test -p spacetimedb-datastore --features
spacetimedb-schema/test -- event_table` (9 unit tests)
- [x] `pnpm format` passes
- [x] Rust SDK integration tests pass (`event_table_tests` module)

---------

Signed-off-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
Co-authored-by: Phoebe Goldman <phoebe@goldman-tribe.org>
Co-authored-by: Jason Larabie <jason@clockworklabs.io>
Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
2026-02-15 22:56:20 +00:00
Tyler Cloutier 2ec07a3f70 Standardize query builder syntax across Rust, TypeScript, and C# (Server/Client) (#4261)
# Description of Changes

Standardizes the query builder API across all three language SDKs (Rust,
TypeScript, C#) for consistency.

**Rust:**
- Rename `Query` struct to `RawQuery`, make `Query` a trait with `fn
into_sql(self) -> String`
- All builder types (`Table`, `FromWhere`, `LeftSemiJoin`,
`RightSemiJoin`) implement `Query<T>` trait
- Views can return `-> impl Query<T>` instead of specifying exact
builder types
- The `#[view]` macro auto-detects `impl Query<T>` and rewrites to
`RawQuery<T>`
- Add `Not` variant to `BoolExpr` with `.not()` method

**TypeScript:**
- Add `ne()` to `ColumnExpression`
- Refactor `BooleanExpr` to `BoolExpr` class with chainable `.and()`,
`.or()`, `.not()` methods
- Make builders valid queries directly (`.build()` deprecated but still
works)
- Deprecate `from()` wrapper — use `tables.person.where(...)` directly
- Merge `query` export into `tables` so table refs are also query
builders
- Add subscription callback form: `subscribe(ctx =>
ctx.from.person.where(...))`
- Unify `useTable` with query builder syntax; deprecate `filter.ts`

**C#:**
- Add `Not()` method to `BoolExpr<TRow>`
- Add `IQuery<TRow>` interface implemented by all builder types
(`Table`, `FromWhere`, `LeftSemiJoin`, `RightSemiJoin`, `Query`)
- Add `ToSql()` to all builder types so `.Build()` is no longer required
- Update `AddQuery` to accept `IQuery<TRow>` instead of `Query<TRow>`

# API and ABI breaking changes

- Rust: `Query<T>` is now a trait (was a struct). The struct is renamed
to `RawQuery<T>`. This is a breaking change for any code that used
`Query<T>` as a type directly.
- TypeScript: `BooleanExpr` is now a `BoolExpr` class (was a
discriminated union type). The `query` export is deprecated in favor of
`tables`.
- C#: `AddQuery` now accepts `Func<QueryBuilder, IQuery<TRow>>` instead
of `Func<QueryBuilder, Query<TRow>>`. Existing `.Build()` calls still
work since `Query<TRow>` implements `IQuery<TRow>`.

# Expected complexity level and risk

3 — Changes touch multiple language SDKs and codegen, but each
individual change is straightforward. The Rust macro rewrite for `impl
Query<T>` detection is the most complex piece. All existing
`.build()`/`.Build()` calls continue to work.

# Testing

- [x] `cargo test -p spacetimedb-query-builder` — 16/16 tests pass
- [x] `cargo check -p spacetimedb` — clean, no warnings
- [x] `cargo check` on views-query, views-sql, views-basic,
views-trapped smoketest modules — all clean
- [x] `cargo test -p spacetimedb-codegen codegen_csharp` — snapshot
updated, passes
- [x] `npm test` (TypeScript) — 101/101 tests pass
- [x] C# QueryBuilder tests — new tests for `Not()`, `IQuery<T>`
interface
- [ ] CI passes
2026-02-13 04:22:49 +00:00
Tyler Cloutier 57b7ef5e79 Limit update() to only work on primary keys (#4279)
## Summary
- Restricts `update()` across all three server-side SDKs (Rust, C#,
TypeScript) to only work on primary key columns, not all unique columns
- Calling `update()` on a non-PK unique column is semantically a
delete+insert — clients won't see it as a row update unless the primary
key stays the same
- Fresh re-implementation of #1862, extended to cover C# and TypeScript
bindings

### Design principle

Primary key is a constraint on columns, not a property of indexes. An
index is unique or not unique — whether `update()` is available is
derived from the column's attributes at the point of use, not stored on
the index.

This differs from #1862 which introduced a `Uniqueness` enum (`No |
Unique | PrimaryKey`) on the index itself. Instead, we keep `is_unique:
bool` and check the column metadata where needed.

### Rust changes
- Add `PrimaryKey` marker trait and `where Col: PrimaryKey` bound on
`UniqueColumn::update()`
- `marker_type()` receives `primary_key_column` and checks the column
directly — no `is_pk` field on the index
- `sdk-test` unique tables use `update_non_pk_by` (delete+insert)
instead of `update_by`
- Benchmarks that used `update()` on `#[unique]` columns changed to
either `#[primary_key]` or delete+insert

### C# changes
- Only emit `Update()` on `UniqueIndex` when the column has `PrimaryKey`
attrs
- Update `unique_*` test reducers in `sdk-test-cs` to use
`Delete()`+`Insert()` instead

### TypeScript changes
- `UniqueIndex` now has only `find` + `delete` (no `update`)
- `AllColumnsPrimaryKey` type-level helper checks column metadata from
the `TableDef`
- `Index` routing conditionally intersects `{ update() }` when columns
are PK
- Runtime only attaches `update` method for PK unique indexes
- `sdk-test-ts` unique tables use delete+insert instead of update
- Type-level test in `schema.test-d.ts` verifies `id.update()` compiles
(PK) and `name2.update` errors (non-PK unique)

## Test plan
- [x] C# codegen tests pass (`dotnet test
crates/bindings-csharp/Codegen.Tests`)
- [x] Rust SDK test module compiles
- [x] Benchmarks compile
- [x] TypeScript type checks pass (`npx tsc --noEmit`)
- [ ] CI passes

Closes #1862
2026-02-13 00:56:54 +00:00
Shubham Mishra b0f3f8d008 Remove __decribe_module_v10__ (#4246)
This reverts commit fd3cdb3d0b.

# Description of Changes
Reverts #4105, We do not actually need `__describe_module_v10__`, as
original describe reducer returns `enum` - `crates:lib::RawModuleDef`
which is extended to add a variant for `V10`

# API and ABI breaking changes
NA
# Expected complexity level and risk
1
# Testing
Existing tests should be enough
2026-02-11 05:36:39 +00:00
joshua-spacetime 30a0ae1473 [2.0 Breaking] Expose RawModuleDefV10 from WASM modules (#4216)
# Description of Changes

Switch Wasm module to `__describe_module_v10__` from
`__describe_module__` to expose `RawModuleDefV10`.

Note: Originally merged into the 2.0 breaking changes branch
https://github.com/clockworklabs/SpacetimeDB/pull/4115.

# API and ABI breaking changes

2.0 breaking change.

# Expected complexity level and risk

1

# Testing

Exising smoketests should be enough.

---------

Co-authored-by: Shubham Mishra <shivam828787@gmail.com>
2026-02-07 17:17:36 +00:00
Noa d3f59480e2 Bump Rust to 1.93.0 (#4180)
# Description of Changes

Required in order to bump rolldown to its latest version, which I'm
planning to do afterwards. I also figure we may as well do this before
releasing a major version.

# Expected complexity level and risk

2

# Testing

n/a
2026-02-06 19:51:53 +00:00
joshua-spacetime 117c7eeb2e [2.0 Breaking] Make connection_id a method on ReducerContext (#4215)
# Description of Changes

Same changes as https://github.com/clockworklabs/SpacetimeDB/pull/4101
but for `connection_id`.

# API and ABI breaking changes

API Breaking

# Expected complexity level and risk

1

# Testing

Pure refactor. Tests and docs have been updated, but no new tests added.
2026-02-06 04:17:36 +00:00
joshua-spacetime 5da08a3dbb [2.0 Breaking]: Remove sender field from [Reducer|View|Procedure]Context (#4208)
# Description of Changes

Makes the `sender` field on `ViewContext` private and exposes a
`sender()` method. Does the same for `ReducerContext` and
`ProcedureContext`.

The purpose of this change: So that the host can determine if/when a
view invokes or reads the `sender`.

Currently, because `sender` is a field, the host assumes that it is
always read. This means views must be materialized per client, even if
the view doesn't actually depend on `sender`, resulting in data
duplication.

The initial solution for this problem was `AnonymousViewContext` which
doesn't have a `sender` field. The better solution is to make `sender` a
method so that it can call into the host and record when it's actually
invoked.

Note, this patch only updates the module API, so the current
implementation does not change. `ViewContext` views are still duplicated
across clients. Changing this requires a new host syscall and for
`sender()` to invoke that syscall. This however is backwards compatible
and can be done anytime after the module APIs for the other languages
(C#, TypeScript, C++) are updated.

Also note that `ReducerContext` and `ProcedureContext` were updated
purely for consistency. There are currently no plans to track reads of
`sender` in these contexts.

# API and ABI breaking changes

Breaks the rust module api.

# Expected complexity level and risk

1

# Testing

N/A
2026-02-05 22:34:40 +00:00
Mazdak Farrokhzad d5dbcf7d15 Pass Reducer/ProcedureContext by reference (#4203)
# Description of Changes

Fixes https://github.com/clockworklabs/SpacetimeDB/issues/2298.

The general idea is to avoid moving around types that are 400+ bytes or
so only to eventually pass them by reference.
Just pass them by ref as soon as possible instead.

# API and ABI breaking changes

None

# Expected complexity level and risk

1

# Testing

Covered by existing tests.
2026-02-04 22:43:31 +00:00
Mazdak Farrokhzad ae15508dee Identifiers: Refactor + Improve type-safety & performance (#4177)
# Description of Changes

The goal of this PR is to:
- Make it easy to switch our backing implementation of identifiers, as
seen in the commit changing to `LeanString`.
- Improve type safety of our identifiers by having every identifier
start with `RawIdentifier` and then `Identifier` is just a wrapper with
validation on construction. `TableName` and `ReducerName` are then just
wrappers around `Identifier`.
- Reduce allocation in `InstanceEnv` by using the now clone-on-write
O(1) + SSO optimized `Identifier`.
- Reduce allocations in the query engine as a consequence of improving
`RawIdentifier` and `Identifier`.
- Have `&'static str` strings be further optimized by avoiding to
allocate even for long ones. This is supported by `impl From<&'static
str> for RawIdentifier` as well as switching to `LeanString`.

The PR results in a roughly 2k TPS improvement over master for WASM +
hash indices. This should also help V8, as this is VM-agnostic.

# API and ABI breaking changes

None

# Expected complexity level and risk

3? Mostly just small changes in many places, but in a sea of small
changes, mistakes can happen.

# Testing

Covered by existing tests.
2026-02-04 20:54:56 +00:00
Shubham Mishra 0b904ad9cf [1/3] RawModuleDefV10 definition and validation. (#4098)
# Description of Changes

Patch:
1. `crates/lib/src/db/raw_def/v10.rs` - a definition as per
https://github.com/clockworklabs/SpacetimeDBPrivate/issues/2412.
2. Refactors `RawModuleDefV9` validation code to dedup some of the core
validation logic, No functionality should change there.
3. Validation logic for new `RawModuleDefV10`.
4. Modify `crates::schema::def::ModuleDef` :
     - To include `raw_module_def_version` 
     -  `visibility` field to existing `RedcuerDef` and `ProcedureDef`
5. It deprecates RLS in favour of Views, If anyoine feel otherwise, let
me know.

Lot of code is duplicated from `RawModuleDefV9` includng tests.

# API and ABI breaking changes
NA, `RawModuleDefV10` is not yet exported by modules.


# Expected complexity level and risk
3? close analyses of structure is important to ensure future
extensibility.


# Testing
For code motion in `RawModuleDefV9` validation: Existing unit tests
seems to cover any functionality change.
For `RawModuleDefV10`: V9 test has been repeated with more `assert`s to
check on `visibility`
2026-01-28 12:30:52 +00:00
Kilian Strunz af4d3f39e4 Make new Uuid type Filterable (#3991)
# Description of Changes

`Uuid` addad in the last update is not filterable even though it is
`Copy` and (imo) obviously _very_ suited to filter.
Promote it to a special `FilterableValue` in the same way as `Identity`
and adjust the docs.

# API and ABI breaking changes

None

# Expected complexity level and risk

1. Only copies the same strategy as `Identity` which is also a newtype
wrapper around a integer like `Uuid`

# Testing

Tested on my project.

After the change:
<img width="586" height="298" alt="image"
src="https://github.com/user-attachments/assets/98e97c16-906b-4e66-b132-676ece40462e"
/>

Before the change:
<img width="1495" height="547" alt="image"
src="https://github.com/user-attachments/assets/da74e49a-1dbd-43ae-9b13-39dcc39c81dc"
/>


You can also test this yourself when adding:
`spacetimedb = { version = "1.11.2", git =
"https://github.com/kistz/SpacetimeDB.git", branch = "uuid-as-filter" }`
to your cargo.toml project

- [x] Tested before and after. Before it was a compiler error afterwards
not.
2026-01-23 00:37:19 +00:00
Shubham Mishra 2560846f22 Rust: client query builder (#4003)
# Description of Changes
Client Query builder for rust, as per proposal -
https://github.com/clockworklabs/SpacetimeDBPrivate/pull/2356.

1. Pach moves query builder to its separate crate, so that it can be
shared between module and sdk.
2. Implements `TypedSubscriptionBuilder` in `sdks/rust` as mentioned in
proposal
3. Modify codegen to extend types to support query builder as mentioned
in proposal
4. a test

# API and ABI breaking changes
NA, additive changes.

# Expected complexity level and risk
2

# Testing
Added a test.

---------

Signed-off-by: Shubham Mishra <shivam828787@gmail.com>
Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
2026-01-22 15:37:22 +00:00
Kilian Strunz 881af7bc8e Fix Hash indices not working (#4060)
# Description of Changes

This pr reexports `PointIndex` and `PointIndexReadOnly` because
currently the new `Hash` indices dont compile when used in projects.
This is because the table macro cant find those two exports.

Maybe @Centril could take a look? :>

# API and ABI breaking changes

None

# Expected complexity level and risk

1. Only fixes a compiler error.

# Testing

- [x] Project compiles now.

Before:
<img width="1454" height="337" alt="image"
src="https://github.com/user-attachments/assets/42df164c-dd09-42b9-97df-a1df719dc3b4"
/>

After:
<img width="1404" height="172" alt="image"
src="https://github.com/user-attachments/assets/0d11158c-daae-44b6-b001-ccccfe0940fd"
/>
2026-01-20 17:02:00 +00:00
Mazdak Farrokhzad 8544e6cf02 Add Hash indices (#3976)
# Description of Changes

Fixes https://github.com/clockworklabs/SpacetimeDB/issues/1122.

Adds hash indices and exposes them through `#[index(hash)]` for Rust
modules,
with support for typescript and C# to come in follow ups.
On the client/sdk side, for now, any index is backed via a BTree/native
index as it is the most general.

A hash index may only be queried through point scan and never ranged
scans.
Attempting a ranged scan results in an error, with the mechanism
implemented in the previous PR
(https://github.com/clockworklabs/SpacetimeDB/pull/3974).



# API and ABI breaking changes

None

# Expected complexity level and risk

2?

# Testing

A test for ensuring that hash indices cannot be used for range scans is
added.
Tests exercising hash indices will come in the next PR.
2026-01-14 09:44:20 +00:00
Tyler Cloutier d78517fd9a Misc docs and small CLI improvements (#3953)
# Description of Changes

This PR does several small things:

1. It removes the explicit `h1` tags on every page, and either uses the
side bar title directly, or puts it in the frontmatter
2. It merges what are currently called quickstarts into a single Chat
App Tutorial
3. It creates new quickstarts which just use `spacetime dev --template`
to get you up and running quickly
4. It adds a "The Zen of SpacetimeDB" page much like the Zen of Python
which goes over the 5 key principles of SpacetimeDB
5. It reorders all Tabs groups so that the ordering is `TypeScript`,
`C#`, `Rust`, `Unreal`, `C++`, `Blueprints` (order of decreasing
popularity).
6. It improves the sidebar navigation by having categories act as
overview pages, and also fixes the breadcrumbs
7. It fixes various small typos and issues
8. Closes #3610 and adds cursor rules files generally
9. It fixes general styling on the docs page by bring it inline with the
UI design:

Old:
<img width="1678" height="958" alt="image"
src="https://github.com/user-attachments/assets/f36efee6-b81a-4463-a179-da68b3a7152e"
/>

New:
<img width="1678" height="957" alt="image"
src="https://github.com/user-attachments/assets/f430f77d-0663-47f2-9727-45cbfe10e4c7"
/>


https://github.com/user-attachments/assets/adc5a78a-ada8-45b5-8078-a45cb81477a3

# API and ABI breaking changes

This PR does NOT change any old links. It does add new pages though.

# Expected complexity level and risk

3 - it's a large change. I manually tested the TypeScript Chat App
Tutorial but I have not gone through the Rust and C# quickstarts.
However, we have testing on the quickstarts and this is text only so can
be carefully reviewed.

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [x] Ran through each step of the Chat App TypeScript tutorial to
ensure it is working
- [x] Ran and tested the styles and the functionality of the side bar

---------

Signed-off-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
Co-authored-by: spacetimedb-bot <spacetimedb-bot@users.noreply.github.com>
Co-authored-by: clockworklabs-bot <clockworklabs-bot@users.noreply.github.com>
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-01-13 00:14:48 +00:00
Mario Montoya 8fb0bcf922 Add UUID built-in convenience type to SpacetimeDB (#3538)
# Description of Changes

Closes
[#3290](https://github.com/clockworklabs/SpacetimeDB/issues/3290).

Adds a new "special" type to SATS, `UUID`, which is represented as the
product `{ __uuid__: u128 }`. Adds versions of this type to all of our
various languages' module bindings libraries and client SDKs, and
updates codegen to recognize it and output references to those named
library types. Adds methods for creating new UUIDs according to the V4
(all random) and V7 (timestamp, monotonic counter and random)
specifications.

# API and ABI breaking changes

We add a new type 

# Expected complexity level and risk

2

it impacts all over the code

# Testing

- [x] Extends the Rust and Unreal SDK tests, and the associated
`module-test` modules in Rust, C# and TypeScript, with uses of UUIDs.
- [x] Extends the C# SDK regression tests with uses of UUIDs.
- [x] Extends the TypeScript test suite with tests with uses of UUIDs.

---------

Signed-off-by: Mario Montoya <mamcx@elmalabarista.com>
Co-authored-by: Phoebe Goldman <phoebe@clockworklabs.io>
Co-authored-by: Jason Larabie <jason@clockworklabs.io>
Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com>
2026-01-02 17:17:24 +00:00
Mazdak Farrokhzad 492e591845 Add WASM point scan ABIs & use them in Rust bindings (#3863)
# Description of Changes

Provides new WASM ABIs:

- `datastore_index_scan_point_bsatn`
- `datastore_delete_by_index_scan_point_bsatn`

These are then used where applicable to speed up `.find(_)` and friends.

Point scans are also used more internally where applicable.

What remains after this is use in C# module bindings and to expose this
in TS as well.

The PR makes TPS go from roughly 36k to 38k TPS on my machine and also
makes a difference in flamegraphs where the time spent in some index
scans are substantially decreased.

# API and ABI breaking changes

None

# Expected complexity level and risk

3? This touches the datastore an how we expose it to modules.

# Testing

Some existing tests now exercise the new ABIs by changing what
`.find(_)` and friends do.

---------

Signed-off-by: Mazdak Farrokhzad <twingoow@gmail.com>
2025-12-12 22:07:54 +00:00
Mario Montoya cdf8391ff3 Add rng support to ProcedureContext on Rust (#3865)
# Description of Changes

As the title says, required for
https://github.com/clockworklabs/SpacetimeDB/pull/3538.

# Expected complexity level and risk

1

# Testing

Will be done on the `uuid` pr.

---------

Signed-off-by: Mario Montoya <mamcx@elmalabarista.com>
Co-authored-by: Phoebe Goldman <phoebe@clockworklabs.io>
2025-12-10 19:05:21 +00:00
Shubham Mishra 6c0b66ad6e filter alias for rust query builder's where method (#3856)
# Description of Changes
As title.


# API and ABI breaking changes
incremental binding.

# Expected complexity level and risk

# Testing
Unit and smoketest
2025-12-10 13:19:32 +00:00
Shubham Mishra d6eff1befe lte and gte operators to rust query builder (#3855)
# Description of Changes
Fixes #3827 

Adding lte and gte support for query_builder in rust.


# API and ABI breaking changes
Incremental change to bindings.

# Expected complexity level and risk
1


# Testing
unit test and smoketest
2025-12-10 12:24:34 +00:00
Shubham Mishra 5100aec3d4 Some more UI tests for Views (#3829)
# Description of Changes
As title

# API and ABI breaking changes
NA

# Expected complexity level and risk
0

---------

Signed-off-by: Shubham Mishra <shivam828787@gmail.com>
Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
2025-12-08 19:33:02 +00:00
Noa afe169ac4a Fix the issues with scheduling procedures (#3816)
# Description of Changes

This reapplies the patch from #3704, and fixes the issues that were
causing it to deadlock.

The reason it was deadlocking was that it allowed for the following
sequence of events:
* `SchedulerActor::handle_queued()` begins mutable tx
* `ModuleHost::disconnect_client()` submits call to `call_reducer(tx:
None)`
* scheduler submits call to `call_reducer(tx: Some)`
* `WasmModuleInstance::disconnect_client` now has to try to take tx
lock, but the scheduler's call_reducer already holds it and is behind it
in the queue

So, I moved most of the logic from `handle_queued` back to being
executed in the module worker thread, but kept the code in
`scheduler.rs` so that it can all be reasoned about locally.

Fixes #3645. Should I uncomment the implementation of
`ExportFunctionForScheduledTable for F: Procedure` now?

# Expected complexity level and risk

2 - there's a chance that this patch hasn't fully fixed the deadlock
issue from #3704, but I'm quite confident.

# Testing

- [x] Manually verified that deadlock no longer occurs - previously,
`while true; do python -m smoketests schedule_reducer -k
test_scheduled_table_subscription; done` would freeze up in only 2 or 3
iterations, but now it can run for 10 minutes without issues.
2025-12-05 22:27:30 +00:00
Shubham Mishra c99a6131c8 [Rust] Query builder Integration. (#3823)
# Description of Changes
Patch contain few different things, required to run query builder end to
end.
Git history seems messed up but it can be reviewed commitwise from -
69c1907b3e.

1. Decouples generic type `T` from table name, as type represents the
`struct` and not table, and there couple be multiple tables implemented
from same struct.
2. modify table macro implementaiton to generate code supporting
`traits` and types required for query builder,
3. Disable aliasing in sql queries for now, as it was causing
semantically wrong query when we were doing joins on `FromWhere` (as
original `Expr` were referencing to original table names).
4. smoketests.


# API and ABI breaking changes
Add `Query<T>` type as Views return type.


# Expected complexity level and risk
2, changes are simple but not splitted up well.

# Testing
1. Added smoketest.

TODO:
ui test.

---------

Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
2025-12-04 17:45:29 +00:00
joshua-spacetime 60048ecbdf [Rust] update module bindings to use new view abi (#3819)
# Description of Changes

Updates the rust module bindings to use new view abi
(`ViewResultHeader`) and updates the return codes for the
`__call_view__` and `__call_view_anon__` module exports. This is in
preparation for `Query` builder support.

# API and ABI breaking changes

Not breaking. Existing modules will continue to use the old abi. New
modules will use the new abi. However previous host versions will not
support modules built using this version of the bindings.

# Expected complexity level and risk

2

# Testing

This is an internal refactor. All existing tests should continue to
pass. The only tests that needed updating were the negative module
compilation tests because the error messages produced by rustc changed.
2025-12-04 08:28:41 +00:00
Shubham Mishra 51ec052509 [Rust] Module-side query builder types (#3797)
# Description of Changes

Implements a query builder for rust modules according to the
[spec](https://github.com/clockworklabs/SpacetimeDBPrivate/blob/master/proposals/0030-views.md#5-query-builder-for-incremental-evaluation).

Look at the tests in `query_builder.rs`.

TODO: Extend return type for views to include `Query` and update the
`#[table]` macro to generate query builder bindings.

# API and ABI breaking changes

This is an additive change. Current modules do not need to be updated
unless they wish to use the query builder.

# Expected complexity level and risk

1.5, Will appreciate comments to better structure code.

# Testing 

[x]: unit tests.

I have also done type safety checks manually from module.

---------

Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
2025-12-04 06:53:26 +00:00
Tamaro Skaljic 87bc15c0b4 Implement DbContext for AnonymousViewContext and ViewContext (#3787)
# Description of Changes

The trait has already been implemented for ReducerContext and TxContext,
but implementation for AnonymousViewContext and ViewContext is still
missing.

## Background why I need this change

In SpacetimeDSL, I currently have the ReducerContext hard-coded as a
prerequisite for creating a DSL instance (see
https://github.com/tamaro-skaljic/SpacetimeDSL/blob/main/src/lib.rs#L9-L33)
.

With the addition of

- ViewContext,
- AnonymousViewContext,
- ProcedureContext, and
- TxContext,

I am now faced with the dilemma that I also have to support SpacetimeDSL
with the other contexts.

I hope to be able to use `spacetimedb::DbContext<DbView =
spacetimedb::Local>` and `spacetimedb::DbContext<DbView =
spacetimedb::LocalReadOnly>` as a common denominator.

(I signed the CLA)

# API and ABI breaking changes

No

# Expected complexity level and risk

1

Signed-off-by: Tamaro Skaljic <49238587+tamaro-skaljic@users.noreply.github.com>
Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
2025-12-02 07:07:37 +00:00
Phoebe Goldman ae9bd74eca Disable scheduling procedures (#3768)
# Description of Changes

We've been unable to get scheduled procedures into the initial release
of procedures due to a nondeterministic hang in some of our tests which
we don't have time to debug. As such, this commit disables scheduled
procedures by:

- Changing the `RawModuleDevV9` validator to reject scheduled
procedures.
- Changing the Rust bindings library's typechecking magic so that
scheduled table annotations referencing procedures will cause a type
error.
- Removes some docs from the Rust bindings library which reference
scheduled procedures.

# API and ABI breaking changes

N/a

# Expected complexity level and risk

1

# Testing

Automated tests should be sufficient.

Prior to merging #3774 , CI for this branch merged with master failed in
the intended way: modules which attempted to define scheduled procedures
failed to typecheck.
2025-11-26 18:40:25 +00:00
Noa de142d4af9 HTTP followup: remove http dep from spacetimedb_lib (#3719)
# Description of Changes

Follow up to #3684. Moves `Error` and `Timeout` out of lib, so that we
don't have to implement `SpacetimeType` for them, and then removes the
http dependency altogether, so that `lib` can be leaner. I also got rid
of the separate `HttpValue` type, since it only really exists to mirror
the `http` crate and typescript won't make use of it.

# Expected complexity level and risk

1

# Testing

n/a - just code movement.
2025-11-21 06:01:21 +00:00
Phoebe Goldman 7df8719b61 Add procedure HTTP request API for WASM modules and the Rust module bindings library (#3684)
# Description of Changes

Closes #3517 .

With this PR, procedures (at least, those defined in Rust modules) can
perform HTTP requests! This is performed through a new field on the
`ProcedureContext`, `http: HttpClient`, which has a method `send` for
sending an `http::Request`, as well as a convenience wrapper `get`.

Internally, these methods hit the `procedure_http_request` ABI call /
host function, which uses reqwest to perform an HTTP request. The
request is run with a user-configurable timeout which defaults and is
clamped to 500 ms.
Rather than exposing the HTTP stream to modules, we download the entire
response body immediately, within the same timeout.

I've added an example usage of `get` to `module-test` which performs a
request against `localhost:3000` to read its own schema/moduledef.

This PR also makes all procedure-related definitions in the Rust module
bindings library `#[cfg(feature = "unstable")]`, as per #3644 . The
rename of the `/v1/database/:name/procedure/:name` route is not included
in this PR, so this does not close #3644 .

Left as TODOs are:
- Metrics for recording request and response size.
- Improving performance by stashing a long-lived `reqwest::Client`
someplace.
  Currently we build a new `Client` for each request.
- Improving performance (possibly) by passing the request-future to the
global tokio executor
  rather than running it on the single-threaded database executor.

# API and ABI breaking changes

Adds new APIs, which are marked as unstable. Adds a new ABI, which is
not unstable in any meaningful way (we can't really do that). Marks
unreleased APIs as unstable. Does not affect any pre-existing
already-released APIs or ABIs.

# Expected complexity level and risk

3 or so: networking is scary, and even though we impose a timeout which
prevents these connections from being truly long-lived, they're still
potentially long-lived on the scale of Tokio futures. It's possible that
running them on the database core is problematic in some way, and so
what I've left as a performance TODO could actually be a
concurrency-correctness issue.

# Testing

- [x] Manually wrote and executed some procedures which make HTTP
requests.
- [x] Added two automated tests to the `sdk-test` suite,
`procedure::http_ok` and `procedure::http_err`, which make successful
and failing requests respectively, then return its result. A client then
makes some assertions about the result.

---------

Co-authored-by: Noa <coolreader18@gmail.com>
2025-11-20 20:47:35 +00:00