mirror of
https://github.com/clockworklabs/SpacetimeDB.git
synced 2026-05-06 15:49:35 -04:00
master
7 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
91d6d5bfca |
Fix primary key migration causing stale schema (#3934) (#4666)
## Summary Fixes #3934. Removing or changing a `#[primary_key]` annotation succeeds on the first re-publish, but the stored schema's `table_primary_key` field in `st_table` is never updated. On the **next** publish, `check_compatible` fails with: ``` Primary key mismatch: self.primary_key: Some(ColId(0)), def.primary_key: None ``` ## Root Cause `auto_migrate_table` handles removing the PK's index and unique constraint, but there was no `AutoMigrateStep` to update the `table_primary_key` field in the system table. ## Fix - Add `AutoMigrateStep::ChangePrimaryKey` variant to the auto-migration planner - Detect `old.primary_key != new.primary_key` in `auto_migrate_table` and emit the step - Add `alter_table_primary_key` to the datastore layer (`mut_tx`, `datastore`, `relational_db`) with proper rollback support via `PendingSchemaChange::TableAlterPrimaryKey` - Handle the step in `auto_migrate_database` - Add migration plan formatter support (termcolor output) ## Repro Script ```bash # 1. Publish with primary key spacetime publish repro --yes # table has #[primary_key] on name # 2. Remove primary key — succeeds spacetime publish repro --yes # removed #[primary_key] # 3. Any change — CRASHES spacetime publish repro --yes # Primary key mismatch error ``` ## Tests - **Unit test** in `crates/core/src/db/update.rs`: Reproduces the exact three-publish sequence from the issue (create table with PK → remove PK → trivial change) - **Smoketest** in `crates/smoketests/tests/smoketests/auto_migration.rs`: Full end-to-end publish flow exercising the same scenario ## Files Changed | File | Change | |------|--------| | `crates/schema/src/auto_migrate.rs` | Add `ChangePrimaryKey` variant + detection | | `crates/schema/src/auto_migrate/formatter.rs` | Format the new step | | `crates/schema/src/auto_migrate/termcolor_formatter.rs` | Colored output | | `crates/datastore/src/locking_tx_datastore/tx_state.rs` | `TableAlterPrimaryKey` pending change | | `crates/datastore/src/locking_tx_datastore/mut_tx.rs` | `alter_table_primary_key` | | `crates/datastore/src/locking_tx_datastore/datastore.rs` | Expose through datastore | | `crates/datastore/src/locking_tx_datastore/committed_state.rs` | Rollback support | | `crates/core/src/db/relational_db.rs` | Expose through RelationalDB | | `crates/core/src/db/update.rs` | Handle step + unit test | | `crates/smoketests/.../auto_migration.rs` | Smoketest | --------- Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com> |
||
|
|
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> |
||
|
|
c044d96a7a |
[TS] schema() takes an object (#4273)
# Description of Changes Implements the rest of the casing proposal. # Expected complexity level and risk <!-- How complicated do you think these changes are? Grade on a scale from 1 to 5, where 1 is a trivial change, and 5 is a deep-reaching and complex change. This complexity rating applies not only to the complexity apparent in the diff, but also to its interactions with existing and future code. If you answered more than a 2, explain what is complex about the PR, and what other components it interacts with in potentially concerning ways. --> # 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! --> - [ ] <!-- maybe a test you want to do --> - [ ] <!-- maybe a test you want a reviewer to do, so they can check it off when they're satisfied. --> |
||
|
|
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 |
||
|
|
7677b5478f |
[TS] Export reducers, etc from a module (#4220)
# Description of Changes Haven't changed `schema()` to accept an object yet, maybe that's for a followup? Now everything exported from the module must be exported from the typescript module. # Expected complexity level and risk <!-- How complicated do you think these changes are? Grade on a scale from 1 to 5, where 1 is a trivial change, and 5 is a deep-reaching and complex change. This complexity rating applies not only to the complexity apparent in the diff, but also to its interactions with existing and future code. If you answered more than a 2, explain what is complex about the PR, and what other components it interacts with in potentially concerning ways. --> # 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! --> - [ ] <!-- maybe a test you want to do --> - [ ] <!-- maybe a test you want a reviewer to do, so they can check it off when they're satisfied. --> |
||
|
|
ce543854e9 |
Unifies server module library and client SDK for TypeScript (and fixes several bugs) (#3559)
# Description of Changes This PR is a very large change to the workings of the TypeScript SDK and as such requires a higher bar of testing than other PRs. However, it does several important things: 1. Unifies the API of the server and client so they not only have the same API, but they actually implement it with the same TypeScript types. This fixes several inconsistencies between them and fixes several small bugs as well. 2. Closes https://github.com/clockworklabs/SpacetimeDB/issues/3365 3. Closes https://github.com/clockworklabs/SpacetimeDB/issues/3431 4. Closes https://github.com/clockworklabs/SpacetimeDB/issues/3435 5. Subsumes the work done in https://github.com/clockworklabs/SpacetimeDB/pull/3447 6. Derives all type information on the client from a single `RemoteModule` type which vastly cleans up the correctness of type checking on the client and helped me to find several small bugs It accomplishes this by changing code generation of TypeScript on the client to code generation approximately what a developer would manually write in their module. The ultimate goal would be to allow the developer to use the types and functions that they define on in their module directly on the client without needing to do any code generation at all, provided they are using TypeScript on the server and client. https://github.com/clockworklabs/SpacetimeDB/issues/3365 is resolved by `.build()`ing the `DbConnection` inside a React `useEffect` rather than doing it directly in line with the render of the provider. In order to do that we needed to not expose the `DbConnection` directly to developers by returning a different type from `useSpacetimeDB`. `useSpacetimeDB` now returns a `ConnectionState` object which is stored as React state and updates when any of the fields change. This change also resolves https://github.com/clockworklabs/SpacetimeDB/issues/3431. https://github.com/clockworklabs/SpacetimeDB/issues/3435 was the issue that initially lead me down the rabbit hole of unifying the server and the client because it was nearly impossible to track down all the various type functions and how they connect to the values that we code generate on the server. After several hours of attempting this, I decided to clean up the types a bit to be more uniform. Implementing the unification between the client and the server also necessitated fully implemented parts of the API that were fully implemented on the server, but were broken or missing on the client. # API and ABI breaking changes [Unification] -> Means that this is breaking behavior for the client SDK, but that the new behavior is identical to the server's existing behavior ## Breaking changes: - Table accessor names and index accessor names are converted to camelCase on the `ctx`, so `ctx.db.foo_bar` is now `ctx.db.fooBar` - [Unification] On the client `my_table.iter()` returns `IterableIterator` instead of an `Array` - [Unification] `module_bindings` now export `TypeBuilder`s for all types instead of a `type MyType` and object `MyType`, so instead of using `MyType` as a type directly, you need to infer the type `MyType` -> `Infer<typeof MyType>`. - [Unification] We no longer generate and export `MyTypeVariants` for sum types (these are now accessed by `Infer<typeof MyType.variants.myVariant>`) - [Unification] `MyType.getTypeScriptAlgebraicType()` has been replaced with `MyType.algebraicType` - `useSpacetimeDB()` no longer takes type parameters - `useTable()` now takes a `TableDef` parameter and type params are inferred - `useTable()` now just returns an `Array` directly instead of a object with `{ rows }` - [Unification] `ctx.reducers.createPlayer(argA, argB)` -> `ctx.reducers.createPlayer({ argA, argB })` - [Unification] `ctx.reducers.onCreatePlayer(ctx, argA, argB)` -> `ctx.reducers.onCreatePlayer(ctx, { argA, argB })` - [Unification] `ctx.reducers.removeOnCreatePlayer(ctx, argA, argB)` -> `ctx.reducers.removeOnCreatePlayer(ctx, { argA, argB })` - [Unification] `myTable.count(): number` -> `myTable.count(): bigint` ## Additive changes: - `Infer<>` now also does `InferTypeOfRow<>` if applicable - Added a `useReducer()` React hook - `module_bindings` now exports a `tables` object with references to all the `TableDef`s - `module_bindings` now exports a `reducers` object with references to all the `ReducerDef`s - Added a new `MyType.create('MyVariant', ...)` function in addition to the `MyType.MyVariant(...)` constructors (this is private) ## Notable things that did not change: - `MyType.serialize(writer: BinaryWriter, value: Infer<typeof MyType>)` and `MyType.deserialize(reader: BinaryReader): Infer<typeof MyType>` are still supported exactly as before. - The `MyType.MyVariant(...)` constructor function on sum types is still present, but implemented with the private `MyType.create('MyVariant', ...)`. We could choose to move away from this API later if we didn't like the variants polluting the namespace # Expected complexity level and risk 4 - This is a deep reaching an complex change for the SDK. For the server, it is much less deep reaching since it reuses much of the same machinery, although it does require thorough testing there as some of the code was modified. This change is fully localized to TypeScript and does not touch the host (or other languages) at all, and therefore only impacts a beta aspect of SpacetimeDB. # 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! --> - [ ] Added regression test for https://github.com/clockworklabs/SpacetimeDB/issues/3435 - [x] Manually tested `test-app` and `test-react-router-app` - [ ] Add test cases for camelCase-ing --------- Signed-off-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com> Co-authored-by: Noa <coolreader18@gmail.com> |
||
|
|
50d58a2858 |
Add modules/benchmarks-ts (#3408)
# Description of Changes Adds `modules/benchmarks-ts`. # API and ABI breaking changes None # Expected complexity level and risk 2? # Testing This is a test. --------- Co-authored-by: Phoebe Goldman <phoebe@goldman-tribe.org> Co-authored-by: Noa <coolreader18@gmail.com> |