Today we have an absolute game changer for SpacetimeDB. SpacetimeDB 1.10 introduces the ability for databases to perform HTTP requests to external services right from within your module! This is one of our most-requested features, and we're very excited to share it with you all.
SpacetimeDB Reducers are extremely powerful. They are atomic, transactional, pure, retryable, and replayable. The challenge was: in order to maintain these properties and guarantees, they need to be isolated from the outside world and can't be allowed to cause any observable side effects.
However, HTTP requests are inherently side-effecting, and are too useful not to have. It turns out the solution is pretty simple: keep reducers side effect free, and introduce a new kind of database function with weaker guarantees and more powers. Enter a new type of SpacetimeDB function: Procedures.
Examples
Just like a reducer, a procedure is a function defined in your module which runs inside the database. Unlike a reducer, procedures don't correspond 1-to-1 with transactions. Instead, you explicitly manage transactions inside the body of your procedure:
#[spacetimedb::procedure]
fn find_highest_level_player(ctx: &mut ProcedureContext) {
let highest_level_player = ctx.with_tx(|ctx| {
ctx.db.player().iter().max_by_key(|player| player.level)
});
match highest_level_player {
Some(player) => log::info!("Congratulations to {}", player.id),
None => log::warn!("No players..."),
}
}Being able to run code in the database without a transaction open opens a lot of possibilities for new APIs we could expose. The first of these, releasing today, is HTTP requests:
#[spacetimedb::procedure]
fn get_request(ctx: &mut ProcedureContext) {
match ctx.http.get("https://example.invalid") {
Ok(response) => {
let (response, body) = response.into_parts();
log::info!(
"Got response with status {} and body {}",
response.status,
body.into_string_lossy(),
)
},
Err(error) => log::error!("Request failed: {error:?}"),
}
}Take a look at the documentation on the new procedure APIs for more details,
and join us on Discord to let us know what other side effects you want APIs for!
As of this release, only Rust and TypeScript modules can define procedures. We're hard at work adding support to C# modules, and will be releasing them soon. We'll also be cleaning up the new APIs in response to your feedback, so for now procedures are unstable and subject to breaking changes.
TypeScript fixes
In this release, we've also fixed quite a few issues which were reported in the new TypeScript SDK.
- This issue by exporting the
SubscriptionHandletype with theREMOTE_MODULEtype applied. - This issue by converting to
camelCasefor column names in code generation. - Fixes an issue where
onMyReducercallbacks were passing arguments as variadic params, while the types indicated they would be passed as an object.onMyReducer((ctx, argA, argB, argC) => {})vs onMyReducer((ctx, { argA, argB, argC}) => {})` - Fixes an issue where the table type name was used instead of the table name in code generation for constructing tables.
- Fixes issue with
ScheduleAtbeing used in non-table types. - Fixes issue where template projects do not use the correct lifecycle reducer setup
- Fixes an issue where
.insert()returns incorrect objects - Fixes an issue where
.update()causes error with.autoInc()field
We intend for TypeScript modules and clients to rapidly approach stability. The most invasive breaking changes have already been made.
What's Changed
- Disable Unreal tests by @bfops in #3711
- Added staging to allowable issuers by @cloutiertyler in #3714
- Add procedure HTTP request API for WASM modules and the Rust module bindings library by @gefjon in #3684
- CI - No discord ping for skipped checks by @bfops in #3718
- Use custom runner for building CLI by @jdetter in #3716
- HTTP followup: remove
httpdep fromspacetimedb_libby @coolreader18 in #3719 - Add C# client SDK procedures by @JasonAtClockwork in #3666
- Upgrade to version 1.9.0 by @jdetter in #3709
- Attach artifacts workflow by @jdetter in #3724
- Add Unreal client SDK procedures by @JasonAtClockwork in #3667
- Views: index readsets by @Shubham8287 in #3706
- Add metrics for subscription queries by @drogus in #3661
- Add
spacetime_worker_reducer_returned_errors_totalmetric by @drogus in #3613 - Remove the dependency on git ls-files from cli/build.rs by @drogus in #3568
- Print internal error when a procedure call fails in sdk test client by @gefjon in #3725
- Revert "Remove the dependency on git ls-files from cli/build.rs (#3568) by @bfops in #3741
- [TS] Implement basic procedure calling by @coolreader18 in #3649
- CI - CLI doc check shouldn't fail on
Cargo.lockdiff by @bfops in #3739 - CI - Clearer CTA in discord post by @bfops in #3738
- Rename the
/database/procedureroute to beunstableby @gefjon in #3723 - [TS] Http procedure API by @coolreader18 in #3731
- [TS] Anonymous transactions by @coolreader18 in #3743
- Fix realtime update for views by @joshua-spacetime in #3747
- Bump hashbrown, foldhash; Fix some compile errors in master by @Centril in #3722
- C# module bindings for Procedures by @rekhoff in #3732
- Add rust sdk tests for views by @joshua-spacetime in #3755
- Add metrics for recording HTTP requests performed by procedures. by @gefjon in #3745
- CI - Migrate off of spacetimedb-runner by @bfops in #3763
- Move docs tests to custom runner by @jdetter in #3699
- Docs: Update docs nav items font weight to 600 by @clockwork-tien in #3721
- [TS] Client-side procedure bindings by @coolreader18 in #3765
- [Typescript] Increased size limits for some deps by @jdetter in #3728
- Procedures: fix scheduling by @Centril in #3704
- First pass at reorganizing the docs and making them nice by @cloutiertyler in #3494
- Revert "Procedures: fix scheduling (#3704)" by @jdetter in #3774
- Upgrade to version 1.10.0 by @jdetter in #3769
- Disable scheduling procedures by @gefjon in #3768
- Set timeout for smoketests by @jdetter in #3772
New Contributors
- @clockwork-tien made their first contribution in #3721
Full Changelog: v1.9.0...v1.10.0