mirror of
https://github.com/clockworklabs/SpacetimeDB.git
synced 2026-05-13 03:08:40 -04:00
bfops/debug-changes
14 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4f0a21f948 |
C# client typed query builder (#3982)
# Description of Changes This PR implements the C# client-side typed query builder, as assigned in https://github.com/clockworklabs/SpacetimeDB/issues/3759. Key pieces: * Added a small C# runtime query-builder surface in the client SDK (`sdks/csharp/src/QueryBuilder.cs`): * `Query` (wraps the generated SQL string) * `Table<TRow, TCols, TIxCols>` (entry point for `All()` / `Where(...)`) * `Col<TRow, TValue>` and `IxCol<TRow, TValue>` (typed column references) * `BoolExpr` (typed boolean expression composition) * SQL identifier quoting + literal formatting helpers (`SqlFormat`) * `Join(...)` with `WhereLeft(...)` / `WhereRight(...)` * `LeftSemijoin(...)` / `RightSemijoin(...)` with `Where(...)` chaining * Extended C# client bindings codegen (`crates/codegen/src/csharp.rs`) to generate: * Per-table/view `*Cols` and `*IxCols` helper classes used by the typed query builder. * A generated per-module `QueryBuilder` with a `From` accessor for each table/view, producing `Table<...>` values. * A generated `TypedSubscriptionBuilder` which collects `Query<TRow>.Sql` values and calls the existing subscription API. * An `AddQuery(Func<QueryBuilder, Query> build)` entry point off `SubscriptionBuilder`, mirroring the proposal’s Rust API. * Fixed a codegen naming collision found during regression testing: * `*Cols`/`*IxCols` helpers are now named after the table/view accessor name (PascalCase) instead of the row type, since multiple tables/views can share the same row type (e.g. alias tables / views returning an existing product type). * Kept `Cols`/`IxCols` off the public surface: * `Table.Cols` and `Table.IxCols` are internal, so consumers only access columns via the `Where(...)`/join predicate lambdas. C# usage examples (mirroring the proposal’s Rust examples) 1) Typed subscription flow (no raw SQL) ```csharp void Subscribe(SpacetimeDB.Types.DbConnection conn) { conn.SubscriptionBuilder() .OnApplied(ctx => { /* ... */ }) .OnError((ctx, err) => { /* ... */ }) .AddQuery(qb => qb.From.Users().Build()) .AddQuery(qb => qb.From.Players().Build()) .Subscribe(); } ``` 2) Typed `WHERE` filters and boolean composition ```csharp conn.SubscriptionBuilder() .OnApplied(ctx => { /* ... */ }) .OnError((ctx, err) => { /* ... */ }) .AddQuery(qb => qb.From.Players().Where(p => p.Name.Eq("alice").And(p.IsOnline.Eq(true))).Build()) .Subscribe(); ``` 3) “Admin can see all, otherwise only self” (proposal’s “player” view logic, but client-side) ```csharp Identity self = /* ... */; conn.SubscriptionBuilder() .AddQuery(qb => qb.From.Players().Where(p => p.Identity.Eq(self) ) ) .Subscribe(); ``` 4) Index-column access for query construction (IxCols) ```csharp conn.SubscriptionBuilder() .AddQuery(qb => qb.From.Players().Where( qb.From.Players().IxCols.Identity.Eq(self) ) ) .Subscribe(); ``` # API and ABI breaking changes None. * Additive client SDK runtime types. * Additive client bindings codegen output. * No wire-format changes. # Expected complexity level and risk 2 - Low to moderate * Mostly additive code + codegen. * The main risk is correctness/compat of generated SQL strings and name/casing conventions across languages; this is mitigated by targeted unit tests + full C# regression test runs. # Testing - [X] Ran run-regression-tests.sh successfully after regenerating C# bindings. - [X] Ran C# unit tests using `dotnet test sdks/csharp/tests~/tests.csproj -c Release` - [X] Added a new unit test suite (`sdks/csharp/tests~/QueryBuilderTests.cs`) validating: * Identifier quoting / escaping * Literal formatting (including `Identity`/`ConnectionId`/`Uuid` hex literals; `U128` integer literal) * null + enum unsupported behavior throws * Boolean expression parenthesization (`And`/`Or`/`Not`) * `Where(...)` overloads including `IxCols`-based predicates * left/right semijoin SQL formatting and predicate chaining |
||
|
|
6f91cfd524 |
Enable RefOption returns from Views to support Views returning a single class (#3964)
# Description of Changes This PR adds a regression test covering nullable reference-type view returns in C# modules (e.g. Account? where Account is a class), as reported in [#3962](https://github.com/clockworklabs/SpacetimeDB/issues/3962). ```csharp public static Account? MyAccount(ViewContext ctx) ``` * Updated the C# regression-test server module to include a reference-type table and views that exercise the RefOption path: * A new public reference-type table row: ```csharp [SpacetimeDB.Table(Name = "account", Public = true)] public partial class Account { ... } ``` * A public at-most-one view that returns a nullable reference type (Account?) via Find(...): ```csharp [SpacetimeDB.View(Name = "my_account", Public = true)] public static Account? MyAccount(ViewContext ctx) { return ctx.Db.account.Identity.Find(ctx.Sender) as Account; } ``` * A second public view that returns null to ensure the “empty result” case is exercised: ```csharp [SpacetimeDB.View(Name = "my_account_missing", Public = true)] public static Account? MyAccountMissing(ViewContext ctx) => null; ``` * Updated ClientConnected to ensure an Account row exists for the connecting identity so the “one row” case is deterministic. * Updated the C# regression-test client to: * Subscribe to the new views: * `SELECT * FROM my_account` * `SELECT * FROM my_account_missing` * Assert correct semantics for nullable reference-type view returns: * MyAccount.Count == 1 * MyAccountMissing.Count == 0 * Updated the regression-test server project to use local C# runtime/codegen project references so the regression module exercises the in-repo generator/runtime behavior (instead of the published SpacetimeDB.Runtime package). # API and ABI breaking changes None. * No changes to public module schema/wire format semantics beyond adding regression-test-only tables/views. * No behavior changes outside the C# regression test module + harness. # Expected complexity level and risk 2 - Low * Changes are isolated to regression tests and project wiring. * The scenario specifically guards the nullable reference-type “Option-like view return” path against regressions. # 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 C# regression tests with no failures in new View tests Signed-off-by: Ryan <r.ekhoff@clockworklabs.io> |
||
|
|
0b91afadef |
Fix C# null string serialization error + add regression coverage for Issue #3960 (#3967)
# Description of Changes This PR fixes a C# SDK/BSATN serialization issue where inserting a `null` string into a non-nullable `string` column could throw an `ArgumentNullException` with an unhelpful stack trace, as reported in [#3960](https://github.com/clockworklabs/SpacetimeDB/issues/3960). * Updated the C# BSATN runtime to reject `null` for non-nullable `string` serialization with a clear, actionable error message (guides users to model nullable strings as `string?` so BSATN encodes an option). * Added BSATN runtime unit tests to cover: * Non-nullable string rejects `null` with an actionable message * Nullable string (`RefOption<string, BSATN.String>`) round-trips `null` * Added end-to-end C# regression-test module + client assertions for #3960: * Inserting `""` into non-nullable `string` succeeds * Inserting `null` into non-nullable `string` fails with the expected message * Inserting `null` into nullable `string?` succeeds and round-trips as `null` # API and ABI breaking changes None. * No schema or wire-format changes. * Behavior change is limited to improving the error surfaced when attempting to serialize null as a non-nullable BSATN `String`, plus stricter input validation for `ConnectionId` / `Identity` parsing. # Expected complexity level and risk 2 - Low * Changes are isolated to regression test coverage. * No impact on valid serialization paths; only affects invalid/malformed inputs and improves diagnostics. # Testing - [X] Ran C# regression-tests client and verified new tests pass. --------- Signed-off-by: Ryan <r.ekhoff@clockworklabs.io> Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com> |
||
|
|
952402d6ab |
Fix reducer errors to return message not stack trace (#3965)
# Description of Changes This PR fixes a C# reducer error-reporting issue where exceptions thrown in reducers were returned to clients with full stack traces, as reported in [#3959](https://github.com/clockworklabs/SpacetimeDB/issues/3959). - Updated the C# reducer host-call error serialization to return only `Exception.Message` (instead of `Exception.ToString()`), preventing server-side stack traces from being leaked to clients. - Added a C# regression-test client assertion to validate reducer failures do not contain stack traces: - `exception.Message` matches the thrown message exactly - the message does not contain newlines or `" at "` stack-trace markers # API and ABI breaking changes None. - No schema or wire-format changes. - Behavior change is limited to the *contents* of reducer error strings returned to clients (stack traces removed). # Expected complexity level and risk 2 - Low - Change is isolated to C# reducer error formatting plus a regression assertion. - Removes unintended information exposure without affecting reducer success paths. # Testing - [X] Ran C# regression-tests client; verified reducer error message is preserved and stack trace is not present. |
||
|
|
82d5a4f6c0 |
Implement SpacetimeType for Result<T, E> (#3790)
# Description of Changes Closes #3673 *NOTE*: C++ part will be in another PR # Expected complexity level and risk 2 Adding a new type touch everywhere # Testing - [x] Adding smoke and unit test --------- Signed-off-by: Ryan <r.ekhoff@clockworklabs.io> Co-authored-by: rekhoff <r.ekhoff@clockworklabs.io> Co-authored-by: Phoebe Goldman <phoebe@goldman-tribe.org> Co-authored-by: Jason Larabie <jason@clockworklabs.io> |
||
|
|
8dd18f078f |
C# bindings: add procedure_http_request support + fix HTTP BSATN wire format to match spacetimedb_lib::http (#3944)
# Description of Changes Rust added procedure-scoped HTTP via the `procedure_http_request` ABI (see Rust PR #3684) to C# host bindings. What changed: 1) Fix for BSATN wire format * Updated C# BSATN wire types for HTTP (`BSATN.Runtime/HttpWireTypes.cs`) to match exactly the Rust stable types: * `spacetimedb_lib::http::Request` fields and order: `method`, `headers`, `timeout`, `uri`, `version` * `spacetimedb_lib::http::Response` fields and order: `headers`, `version`, `code` * Header pairs are (`name: string, value: bytes`); no additional metadata is encoded. * Added explicit “do not reorder/extend” note in the C# wire type file since the host BSATN-decodes these bytes directly and may trap on mismatch. 2) C# runtime HTTP client implementation * Implemented `ProcedureContext.Http` support (`Runtime/Http.cs`) that: * BSATN-serializes `HttpRequestWire` + sends body bytes via `procedure_http_request` * On success, BSATN-decodes `HttpResponseWire` and returns `(response, body)` as a typed `HttpResponse` * On `HTTP_ERROR`, decodes the error payload as a BSATN `string` * On `WOULD_BLOCK_TRANSACTION`, returns a stable error message (host rejects blocking HTTP while a mut tx is open) * Clamps timeouts to 500ms max (matching host behavior documented on the Rust side) 3) ABI wiring / import plumbing * Added the `procedure_http_request` import to the C# wasm shim (`Runtime/bindings.c`) under the `spacetime_10.3` import module. * Verified the generated C# P/Invoke signature matches the host ABI (request ptr/len, body ptr/len, out `[BytesSource; 2]`). 4) Procedure entrypoint contract (trap vs errno) * Updated/clarified the module procedure trampoline behavior (`Runtime/Internal/Module.call_procedure`): it must either return `Errno.OK` or trap (log + rethrow). This mirrors the host’s expectations and avoids “unexpected errno values from guest entrypoints” behavior. Behavioral notes vs Rust * Rust bindings may `expect(...)`/panic on “should never happen” serialization failures; C# runtime explicitly avoids throwing across the procedure boundary for the HTTP client path and instead returns `Result.Err` for unexpected failures. This prevents whole-module traps from user-space HTTP usage while still surfacing rich errors. * The host remains authoritative on timeout enforcement; C# now mirrors the effective host clamp (500ms) to keep behavior aligned. # API and ABI breaking changes No new host ABI introduced, and does not change the syscall signature. * This is not an ABI “break” in the host, but it is a guest-side wire compatibility correction: older C# guests built with the incorrect wire types could cause the host to trap during BSATN decode. After this PR, C# guests are compatible with the host’s expected layout. **Adds API**: `ProcedureContextBase.Http` is available for procedures No existing public types/method signatures are removed * A notable difference from Rust's panic behavior is that Rust code sometimes `expect(...)`s and may panic/trap on internal “should not happen” cases. On the other hand, C#'s `HttpClient.Send` explicitly converts unexpected failures into `Result.Err` to avoid trapping the module. This is a behavioral difference, but not an API break. # Expected complexity level and risk 2 - Mostly just creating equivalents to the Rust version. # Testing C# regression tests updated to cover: - [X] Successful request path (`ReadMySchemaViaHttp`) - [X] Invalid request path (`InvalidHttpRequest`) returning error without trapping Testing performed: - [X] Full regression suite run against local node (see chat log); no wasm traps, all suites reported `Success`. --------- Signed-off-by: Ryan <r.ekhoff@clockworklabs.io> |
||
|
|
f906be6bd9 |
Fixed Nullable value-type fields in Views in C# module causing excessive logging (#3949)
# Description of Changes This PR fixes a C# codegen performance/behavior issue triggered by views that include nullable value-type fields (e.g. `DbVector2?`), as reported in #3914. * Updated the C# BSATN code generator to emit non-boxing equality for `Nullable<T>` members by using `System.Nullable.Equals(a, b)` rather than `a.Equals(b)` (which can box and cause excessive host logging/work in view diff/equality paths). This causes code generation to change from something like: ``` csharp // From: var ___eqNullableIntField = this.NullableIntField.Equals(that.NullableIntField); // To: var ___eqNullableIntField = System.Nullable.Equals( this.NullableIntField, that.NullableIntField ); ``` * Added a regression scenario to the C# regression-test module that exercises the problematic pattern: * A table containing a nullable struct field (`DbVector2? Pos`). * A public view that returns rows containing that nullable field. * A reducer to mutate the nullable field from `some` → `none` → `some` to force view re-evaluation and diffing. * Updated the regression-test client to: * Subscribe to the new view. * Validate that the view evaluates successfully and contains the expected rows. * Call the reducer and validate view state after updates. * Fail the test if view evaluation/diffing produces errors. # API and ABI breaking changes None. * No changes to public SpacetimeDB schema or wire format semantics. * Changes are limited to generated equality code and regression tests. # Expected complexity level and risk 2 - Low * The codegen change is small and localized (special-casing `System.Nullable<T>` equality generation). * Risk is primarily around subtle behavior differences in equality for nullable value types; however, `System.Nullable.Equals` matches the expected semantics and avoids boxing. * Regression tests specifically cover the nullable-struct-in-view scenario to guard against regressions. # 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 the C# regression test suite via `run-regression-tests.sh` and confirmed no errors. |
||
|
|
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> |
||
|
|
f309ea93f9 |
Removes C# regression test of TimestampCapabilities (#3908)
# Description of Changes Removes the `TimestampCapabilities` test from the C# SDK's regression test suite, due to creating inconsistent failures in automated CI testing. # API and ABI breaking changes Not API/ABI breaking # Expected complexity level and risk 1 # Testing - [X] Ran locally, no failures in building or running C# regression tests |
||
|
|
39f01289e5 |
C# implementation of Transactions for Procedures (#3809)
# Description of Changes Implements the C# equivalent of #3638 This implement uses inheritance, where abstract base classes (like `ProcedureContextBase` in `ProcedureContext.cs`) store the core of the implementation, and then generated wrappers (like `ProcedureContext` in the generated FFI.cs file) inherit from them. For error handling, we work like Rust's implementation of `Result<T,E>` but we require `where E : Exception` because of how exceptions work in C#. Transaction-level failures come back as a `TxOutcome` and user errors should follow the `Result<T,E>` pattern. In this implementation, we have `UnwrapOrThrow()` throws exceptions directly because of C#'s error handling pattern. Unlike the Rust implementation's direct `Result` propagation, we are using an `AbortGuard` pattern (in `ProcedureContext.cs`) for exception handling, which uses `IDisposable` for automatic cleanup. Most changes should have fairly similar Rust-equivalents beyond that. For module authors, the changes here allow for the transation logic to work like: ```csharp ctx.TryWithTx<ResultType, Exception>(tx => { // transaction logic return Result<ResultType, Exception>.Ok(result); }); ``` This change includes a number of tests added to the `sdks/csharp/examples~/regression-tests/`'s `server` and `client` to validate the behavior of the changes. `server` changes provide further usage examples for module authors. # API and ABI breaking changes Should not be a breaking change # Expected complexity level and risk 2 # Testing - [x] Created Regression Tests that show transitions in procedures working in various ways, all of which pass. |
||
|
|
cb35104c0f |
Export __call_view__ in C# (#3691)
# Description of Changes 1. Updates the Replication Tests in `sdks/csharp/examples~/regression-tests` to include better coverage of Views 2. Added missing linkage for __call_view__ and __call_view_anon__ 3. Updated *ViewDispatcher Invoke to transform BSATN.ValueOption<> into BSATN.List<> 4. Fixed issues with the indexing of views to match correctly during __call_view__ and __call_view_anon__ # API and ABI breaking changes No # Expected complexity level and risk 2 # Testing - [x] Running `run-regression-tests.sh` passes. --------- Signed-off-by: rekhoff <r.ekhoff@clockworklabs.io> Signed-off-by: Jason Larabie <jason@clockworklabs.io> Co-authored-by: Jason Larabie <jason@clockworklabs.io> Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com> Co-authored-by: joshua-spacetime <josh@clockworklabs.io> |
||
|
|
b5eac84caf |
Add a RemoteQuery regression test to C# SDK (#3163)
# Description of Changes Add a RemoteQuery regression test to C# SDK to address issue: https://github.com/clockworklabs/SpacetimeDB/issues/3064 This adds on to existing regression tests, creating a rather small change. # API and ABI breaking changes Not breaking change # Expected complexity level and risk 1 # Testing - [X] Ran `dotnet test`, all tests pass |
||
|
|
b6f8362b75 |
Implement OnUnhandledReducerError (#295)
## Description of Changes SDK side of https://github.com/clockworklabs/SpacetimeDB/pull/2636 Addresses https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/issues/281 ## API - [ ] This is an API breaking change to the SDK ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/2636 ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: jgilles/on-unhandled-reducer-error ## Testing - [ ] Add a test that this works to the regression-tests example module |
||
|
|
3543132c7d |
Fix for unsubscribe bug + regression tests (#264)
## Description of Changes This PR fixes one issue and adds regression tests for it, plus another issue. These regression tests are run on CI. You can also run them locally -- run a local spacetime instance and then `tools~/run-regression-tests.sh ../SpacetimeDB`). ### Issue 1: Unsubscribe is non-functional See https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/issues/279. This was a coding mistake made during the rush to 1.0. It was easily fixed. ### Issue 2: Indexes not tracking deletes This was recently discovered by the BitCraft team. The problem was introduced in https://github.com/clockworklabs/com.clockworklabs.spacetimedbsdk/commit/cefc727b7693fe97e3dd848fef2bb17bf20c8be6 which introduced `RemoteTableHandle<EventContext, Row>.IndexBase<Column>`. This class stores a `Dictionary<Column, List<Row>>` to allow fast filtering. It relies on `List<Row>.Remove` to remove elements from a list when a row delete is received. `List<Row>.Remove` relies on `Row.Equals` to determine when elements are equal. `Row.Equals` formerly was not implemented for `[SpacetimeDB.Type]`s or for generated Row types. So, this didn't work. Now it does: it was fixed by https://github.com/clockworklabs/SpacetimeDB/pull/239 . So all this PR does to address this issue is add a regression test. ## API - [x] This is an API breaking change to the SDK The interface IDbConnection was changed; however, this changed part of the interface is `internal`, so this should be entirely invisible to users. ## Requires SpacetimeDB PRs https://github.com/clockworklabs/SpacetimeDB/pull/239 (merged) ## Testsuite *If you would like to run the your SDK changes in this PR against a specific SpacetimeDB branch, specify that here. This can be a branch name or a link to a PR.* SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [x] Added a repro for both issues - [x] Added the repro to CI - [x] Fixed both issues |