Commit Graph

131 Commits

Author SHA1 Message Date
Phoebe Goldman 41eec04ea6 Respect updates to st_table during replay (#3937)
# Description of Changes

Prior to this commit, we had special handling for deletes from
`st_table` during replay, but we did not pair them with inserts to form
updates, instead only treating the delete as a dropped table.

With this commit, we record inserts to `st_table` which will form update
pairs during replay, and handle them appropriately, updating the table's
schema and not dropping the table.

There is a tricky case where a table exists but is empty, and then
within a single transaction:
- The table undergoes a migration s.t. its `table_access` or
`primary_key` changes.
- At least one row is inserted into the table.

In this case, the in-memory table structure will not exist at the point
of the `st_table` insert, but will be created before the corresponding
`st_table` delete, meaning there will be two conflicting `st_table` rows
resident. To handle this case, `CommittedState` tracks a side table,
`replay_table_updated`, which stores a `RowPointer` to the correct
most-recent `st_table` row for the migrating table.

I've also renamed the one previously-extant replay-only side table,
`table_dropped`, to include the `replay_` prefix, which IMO improves
clarity. And I've made it so `replay_table_dropped` is cleared at the
end of each transaction, as the previous behavior of continuing to
ignore a table that should be unreachable masked errors which would have
been helpful when debugging this issue.

This PR also includes an extended error message when encountering a
unique constraint violation while replaying, which I found helpful while
debugging.

# API and ABI breaking changes

N/a

# Expected complexity level and risk

2 - replay is complicated and scary, but this PR isn't gonna make things
*more* broken than they already were.

# Testing

- [x] Manually replayed a commitlog which included a migration that
altered a table's `table_access`, which was previously broken but now
replays successfully.
2025-12-30 20:11:14 +00:00
Mazdak Farrokhzad 8e3af49f64 Reuse buffers in ServerMessage<BsatnFormat> (#2911)
# Description of Changes

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

Defines a global pool `BsatnRowListBuilderPool` which reclaims the
buffers of a `ServerMessage<BsatnFormat>` and which is then used when
building new `ServerMessage<BsatnFormat>`s.

Notes:
1. The new pool `BsatnRowListBuilderPool` reports the same kind of
metrics to prometheus as `PagePool` does.
2. `BsatnRowListBuilder` now works in terms of `BytesMut`.
3. The trait method `fn to_bsatn_extend` is redefined to be capable of
dealing with `BytesMut` as well as `Vec<u8>`.
4. A trait `ConsumeEachBuffer` is defined from
`ServerMessage<BsatnFormat>` and down to extract buffers.
`<ServerMessage<_> as ConsumeEachBuffer>::consume_each_buffer(...)` is
then called in `messages::serialize(...)` just after bsatn-encoding the
entire message and before any compression is done. This is the place
where the pool reclaims buffers.

# Benchmarks

Benchmark numbers vs. master using `cargo bench --bench subscription --
--baseline subs` on i7-7700K, 64GB RAM:

```
footprint-scan          time:   [21.607 ms 21.873 ms 22.187 ms]
                        change: [-62.090% -61.438% -60.787%] (p = 0.00 < 0.05)
                        Performance has improved.

full-scan               time:   [22.185 ms 22.245 ms 22.324 ms]
                        change: [-36.884% -36.497% -36.166%] (p = 0.00 < 0.05)
                        Performance has improved.
```

The improvements in `footprint-scan` are mostly thanks to
https://github.com/clockworklabs/SpacetimeDB/pull/2918, but 7 ms of the
improvements here are thanks to the pool. The improvements to
`full-scan` should be only thanks to the pool.

# API and ABI breaking changes

None

# Expected complexity level and risk

2?

# Testing

- Tests for `Pool<T>` also apply to `BsatnRowListBuilderPool`.
2025-12-18 23:02:36 +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
Mazdak Farrokhzad e5f1558ec7 Don't panic in datastore_index_scan_range_bsatn on invalid ranges (#3746)
# Description of Changes

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

# API and ABI breaking changes

None

# Expected complexity level and risk

1

# Testing

A proptest `empty_range_scans_dont_panic` is added.
2025-12-10 13:45:36 +00:00
Mazdak Farrokhzad ed2a18cff7 Bump hashbrown, foldhash; Fix some compile errors in master (#3722)
# Description of Changes

There were mentions of `hashbrown` in the repo that did not go through
`spacetimedb_data_structures::map`.
This caused compile errors on master when running certain tests locally.
These have been replaced with the proper imports.

The PR also bump hashbrown to 0.16.1 and foldhash to 0.2.0.

# API and ABI breaking changes

None

# Expected complexity level and risk

2

# Testing

Covered by existing tests.
2025-11-25 12:17:24 +00:00
joshua-spacetime 0de8910e2a Atomic view update (#3624)
# Description of Changes

Updates views atomically on commit, but before downgrading to a
read-only transaction for subscription evaluation.

What this patch does:
1. Renames `ViewId` to `ViewFnPtr`
2. Renames `ViewDatabaseId` to `ViewId`
3. Removes the `module_rx` module watcher from the subscription manager
4. Refactors read sets to only track table scans (index key tracking
will be added later)
5. Drops read sets and removes rows from `st_view_sub` when dropping a
view in an auto-migrate
6. Re-evaluates and updates views (`call_views_with_tx`) from
`call_reducer_with_tx` for any view whose read set overlaps with the
reducer's write set
7. Does the same for sql dml

# API and ABI breaking changes

None

# Expected complexity level and risk

3

It's a bit of a messy diff.

# Testing

- [x] Integrate with
https://github.com/clockworklabs/SpacetimeDB/pull/3616

---------

Signed-off-by: joshua-spacetime <josh@clockworklabs.io>
Co-authored-by: Shubham Mishra <shivam828787@gmail.com>
2025-11-11 04:26:52 +00:00
Shubham Mishra 75c6e67c3c Views: Host interface for WASM modules (#3548)
# Description of Changes
Host implementation to invoke `call_view` method.
 I also covers:
1. API `MutTxId::is_materialized`to check if existing view exisits and
updated.
 2. Update in readsets logic to remove stale views.
 3. sql caller implmentation.

# API and ABI breaking changes
NA

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.
3
2025-11-06 21:14:00 +00:00
joshua-spacetime 30b8eaccf1 Decrement view subscriber count on disconnect (#3547)
# Description of Changes

Refactored `st_view_client` and renamed it `st_view_sub` which tracks
the number of clients subscribed to a view. On disconnect, we decrement
the `num_subscribers` column in the appropriate rows. An async task will
be in charge of cleaning up views (and their read sets) whose subscriber
count has gone to zero (not in this patch).

On module init, we clear the entirety of each view table.

# API and ABI breaking changes

None. Technically this updates the schema of a system table, but the
system table was added and modified between releases.

# Expected complexity level and risk

~2

Need to make sure we cover all cases so that we don't leave dangling
data. Making these tables ephemeral in the future should simplify this.

# Testing

Will add tests once we can subscribe to views
2025-11-06 07:55:17 +00:00
joshua-spacetime 92cef1abe7 View resolution in sql (#3570)
# Description of Changes

Not many changes were required for the query compiler to be able to
resolve views. This is because the query engine can always assume a view
is materialized and therefore has a backing table. So from the
perspective of the query engine, a view is just another table with one
small caveat: The physical table in the datastore has two internal
metadata columns - `sender` and `arg_id`. These columns are not user
facing and so should be hidden from name resolution/type checking.

# API and ABI breaking changes

None

# Expected complexity level and risk

1.5

# 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] SQL type checking tests
2025-11-05 08:31:41 +00:00
joshua-spacetime 542d26d7ff add system tables for views (#3419)
# Description of Changes

<!-- Please describe your change, mention any related tickets, and so on
here. -->

This patch defines the system table schemas for views and allocates IDs
for them. It **does not** populate these tables.

# API and ABI breaking changes

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

None

# 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. -->

1

# 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! -->

Tests will be added in the patch that populates these tables
2025-10-17 19:01:22 +00:00
samuel.engstrom@arvikasoft.se 3075ca4fba Add forgotten variance to table_index::can_merge (#3391)
TableIndex merge logic to was missing  variants.

# Description of Changes

This pull request fixes an issue where the TableIndex::can_merge
function was missing match variants.

# API and ABI breaking changes

None.

# Expected complexity level and risk

1 / 5 (Trivial)
This is a very low-risk change. It simply adds a few lines to a match
statement

# Testing

Manual testing confirm that creating two tables with indices with the
for the missing variants no longer causes a panic.
2025-10-15 17:05:54 +00:00
Noa 619b8ce021 Bump Rust to 1.90 (#3397)
# Description of Changes

Necessary for pulling in rolldown.

# API and ABI breaking changes

None

# Expected complexity level and risk

1, with the caveat that this updates the Rust version and therefore
touches all the code.

# Testing

- [ ] Just the automated testing
2025-10-09 20:41:25 +00:00
Mazdak Farrokhzad 2743d0bae3 SATS: impl ser/de for tuples (#3292)
# Description of Changes

Implements `Serialize` and `Deserialize` for tuples.
Extracted from https://github.com/clockworklabs/SpacetimeDB/pull/3276.

# API and ABI breaking changes

None

# Expected complexity level and risk

2

# Testing

A test `roundtrip_tuples_in_different_data_formats` is added.
2025-09-25 15:30:10 +00:00
Shubham Mishra 94809dc277 datastore: add columns support (#3230)
# Description of Changes
- `add_columns_to_table` api to handle `AutoMigrateStep::AddColumns` --
Look at doc comment for more Info.

depends on: https://github.com/clockworklabs/SpacetimeDB/pull/3261

TODO: handle `AutoMigrateStep::DisconnectAllUsers`.

# API and ABI breaking changes
N/A.

# Expected complexity level and risk
2? Changes are not in hotpath but a bug in migration can corrupt tables.

# Testing
a test to exercise the API.

---------

Signed-off-by: Mazdak Farrokhzad <twingoow@gmail.com>
Signed-off-by: Shubham Mishra <shivam828787@gmail.com>
Co-authored-by: Mazdak Farrokhzad <twingoow@gmail.com>
2025-09-23 18:31:12 +00:00
Mazdak Farrokhzad e93de33111 datastore: add clear_table and fix drop_table (#3214)
# Description of Changes

Aternative to and closes
https://github.com/clockworklabs/SpacetimeDB/pull/3210.
This version relies on `pending_schema_changes`.
The first commit adds `clear_table` to the datastore that's efficient
and can be exposed to the module ABI in a follow up.
The second commit fixes `drop_table`.

# API and ABI breaking changes

None

# Expected complexity level and risk

3?

# Testing

`test_drop_table_is_transactional` is amended to check `TxData`.

---------

Signed-off-by: Mazdak Farrokhzad <twingoow@gmail.com>
Co-authored-by: Shubham Mishra <shubham@clockworklabs.io>
Co-authored-by: Shubham Mishra <shivam828787@gmail.com>
2025-09-23 11:48:49 +00:00
Phoebe Goldman aeeb35f0bb Improve error reporting for invalid column-type-changing automigrations (#3202)
# Description of Changes

Title. When validating column type changes in `Table::change_columns_to`
and comparing layouts in `RowTypeLayout::is_compatible_with`, return
structured error objects which describe the mismatch.

I made this change while debugging the issue that led to #3203 , where
`change_columns_to` returned an error during replay of an automigration
which had succeeded the first time. The original error contained enough
information to debug, but it was presented in a noisy and unhelpful way,
so I wrote this patch to get better diagnostics.

Per @Centril 's comments, these errors are for internal assertions, not
user-facing error reporting, so we value fail-fast rather than error
hygiene and choose not to use the `ErrorStream` combinator.

Also note that I sprinkled `Box`es around some large-ish error types to
quiet
https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err
.

# API and ABI breaking changes

N/a

# Expected complexity level and risk

1.

# Testing

Manual testing with BitCraft. As this is purely altering the error
reporting for non-user-facing assertions, I don't believe any further
testing is necessary.
2025-08-29 17:02:27 +00:00
Zeke Foppa f6f0909ea4 Update all licenses (#3002)
# Description of Changes

We recently merged several repos together. This PR clarifies the license
terms for several subdirectories, as well as the relationship between
the licenses.

The licenses in our subdirectories have become symbolic links to
licenses in our toplevel `licenses` directory. For any particular
subdirectory's license file in the diff, you can click `... -> View
file` and then click on the text that says "Symbolic Link" on that page.
This will take you to the license file that it links to.

I have also updated the `tools/upgrade-version` script to update the
change date in the new `licenses/BSL.txt` file.

# API and ABI breaking changes

None.

# Expected complexity level and risk

1

# Testing

None. Only changes to license files.

---------

Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2025-08-12 18:20:58 +00:00
Noa 742303ca49 Bump rust-toolchain to rust 1.88 (#2749)
Co-authored-by: Mazdak Farrokhzad <twingoow@gmail.com>
2025-07-15 17:39:41 +00:00
Mazdak Farrokhzad 34201c6e02 Fix AlgebraicTypeLayout::is_compatible_with (#2932) 2025-07-11 12:59:09 +00:00
Mazdak Farrokhzad 6a8cd7e9e1 Extract object_pool module from PagePool (#2920) 2025-07-04 13:47:26 +00:00
Mazdak Farrokhzad 1166d68e65 Extract spacetimedb-memory-usage & Nix bindings dep on spacetimedb-data-structures (#2919) 2025-07-04 12:54:00 +00:00
Mazdak Farrokhzad 0c3635188d Auto-migrate: Allow adding new variants at the tail (#2874) 2025-06-27 17:29:31 +00:00
Mazdak Farrokhzad bc4fea2070 TypedIndex: add special cases for F{32,64} (#2885) 2025-06-22 16:37:53 +00:00
Mazdak Farrokhzad ad39b7b8a8 spacetimedb_execution: avoid get_row_ref (#2806) 2025-06-04 17:44:35 +00:00
Viktor Szépe f6da9e1f5f Fix typos (#2812)
Signed-off-by: Viktor Szépe <viktor@szepe.net>
2025-06-04 16:33:32 +00:00
Mazdak Farrokhzad f3c899e998 Consider deleted committed rows in MutTxId::create_index (#2805)
Signed-off-by: Mazdak Farrokhzad <twingoow@gmail.com>
Co-authored-by: Phoebe Goldman <phoebe@clockworklabs.io>
2025-05-28 16:10:00 +00:00
Mazdak Farrokhzad 800af9b8f5 Page::reset_for: stop zeroing pages (#2804)
Bypassed rules because of a cla automation issue. All checks passed otherwise.
2025-05-28 10:22:17 -04:00
Mazdak Farrokhzad c3803ae278 Cheaper Table::clone_structure (#2776)
Signed-off-by: Phoebe Goldman <phoebe@goldman-tribe.org>
Co-authored-by: Phoebe Goldman <phoebe@clockworklabs.io>
2025-05-23 13:40:35 +00:00
joshua-spacetime ade5858269 Re-enable page bool with default size of 128 pages (#2769) 2025-05-22 14:17:36 +00:00
Mazdak Farrokhzad 32c4ee8989 datastore: apply schema changes immediately to committed state. (#2685)
Co-authored-by: Tyler Cloutier <cloutiertyler@aol.com>
2025-05-21 16:27:21 +00:00
Mazdak Farrokhzad 05e171ccec Cache with_label_values more & don't do metrics while holding lock (#2734) 2025-05-21 14:11:41 +00:00
Mazdak Farrokhzad 373e47db39 PagePool::{default -> new_for_test} + temporary hack for IN_MEMORY_CONFIG / test_index_scans (#2707) 2025-05-12 13:15:07 +00:00
Mazdak Farrokhzad eb589728c6 Allocate pages using a mult-tenant lock-free pool (#2587) 2025-04-28 17:35:19 +00:00
Zeke Foppa 118e59de14 CI - Do some basic checks that crates are publishable (#2660)
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2025-04-23 17:08:43 +00:00
Mazdak Farrokhzad 65e12b994b datastore: fix two inserts in tx state with unique idx (#2610) 2025-04-17 19:20:47 +00:00
Noa 483a9488e2 Update rand (#2568) 2025-04-11 17:39:41 +00:00
Mazdak Farrokhzad c39f7fa64c Plain enums as index keys with specialized indices (#2506) 2025-04-09 18:52:15 +00:00
Mario Montoya f9f38543c8 Add readmes to all implementation crates specifying that they do no offer stable interfaces (#2320) 2025-03-06 19:50:17 +00:00
Phoebe Goldman aedc601145 Rename Address to ConnectionId (#2220)
Signed-off-by: Phoebe Goldman <phoebe@goldman-tribe.org>
Co-authored-by: James Gilles <jameshgilles@gmail.com>
Co-authored-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
2025-02-10 00:40:16 +00:00
Mazdak Farrokhzad b50b6841f1 Add direct indices to datastore (#2221) 2025-02-07 01:06:38 +00:00
Mazdak Farrokhzad 25d74091c3 Make MutTxId::update really idempotent wrt. TxData (#2212) 2025-02-05 20:40:02 +00:00
Phoebe Goldman d839657008 Data size SKU for billing (#2098) 2025-02-03 14:15:30 +00:00
Mazdak Farrokhzad 6f20597600 Make check_and_insert & find_old_row and friends do less checks (#2192) 2025-01-31 15:00:19 +00:00
Mazdak Farrokhzad 6630a90ee1 Switch DeleteTable impl to one based on FixedBitSet (#2183) 2025-01-29 17:15:17 +00:00
Noa 293aebaef9 Bump to Rust 1.84 (#2001) 2025-01-28 23:11:29 +00:00
Mazdak Farrokhzad 5b5a0a6515 Cache whether a Table is a scheduler table, avoiding fetching the schema (#2141) 2025-01-28 19:57:15 +00:00
Mazdak Farrokhzad afdc0d67dd Add the update ABI (#2137)
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2025-01-27 19:38:18 +00:00
Phoebe Goldman d171b44a89 Don't create indexes during bootstrapping; wait until after replay (#2161) 2025-01-23 19:41:39 +00:00
Mazdak Farrokhzad a1573af5a1 Fix unique index + MutTxId::insert not un-deleteting (#2156) 2025-01-22 09:51:34 +00:00
Mazdak Farrokhzad 6f428f3afb Make the key of Table.indexes be IndexId (#2124) 2025-01-17 18:42:54 +00:00