From 333da21ac53cfdd4e8abaaa76ee0dc9d77fa43b5 Mon Sep 17 00:00:00 2001 From: James Gilles Date: Thu, 21 Nov 2024 16:39:39 -0500 Subject: [PATCH 1/2] Fix declaration order of ScheduleAt in C# and add some tests to sdk-test[-cs] --- .../bindings-csharp/BSATN.Runtime/Builtins.cs | 16 +- .../module_bindings/indexed_table_2_table.rs | 91 +++++++++++ .../module_bindings/indexed_table_2_type.rs | 20 +++ .../module_bindings/indexed_table_table.rs | 91 +++++++++++ .../src/module_bindings/indexed_table_type.rs | 19 +++ .../test-client/src/module_bindings/mod.rs | 36 +++++ .../module_bindings/scheduled_table_table.rs | 143 ++++++++++++++++++ .../module_bindings/scheduled_table_type.rs | 21 +++ .../send_scheduled_message_reducer.rs | 93 ++++++++++++ modules/sdk-test-cs/Lib.cs | 35 ++++- modules/sdk-test/src/lib.rs | 23 +++ 11 files changed, 578 insertions(+), 10 deletions(-) create mode 100644 crates/sdk/tests/test-client/src/module_bindings/indexed_table_2_table.rs create mode 100644 crates/sdk/tests/test-client/src/module_bindings/indexed_table_2_type.rs create mode 100644 crates/sdk/tests/test-client/src/module_bindings/indexed_table_table.rs create mode 100644 crates/sdk/tests/test-client/src/module_bindings/indexed_table_type.rs create mode 100644 crates/sdk/tests/test-client/src/module_bindings/scheduled_table_table.rs create mode 100644 crates/sdk/tests/test-client/src/module_bindings/scheduled_table_type.rs create mode 100644 crates/sdk/tests/test-client/src/module_bindings/send_scheduled_message_reducer.rs diff --git a/crates/bindings-csharp/BSATN.Runtime/Builtins.cs b/crates/bindings-csharp/BSATN.Runtime/Builtins.cs index ed60d29fe16..52c829831ce 100644 --- a/crates/bindings-csharp/BSATN.Runtime/Builtins.cs +++ b/crates/bindings-csharp/BSATN.Runtime/Builtins.cs @@ -304,30 +304,30 @@ public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // [SpacetimeDB.Type] - we have custom representation of time in microseconds, so implementing BSATN manually public abstract partial record ScheduleAt - : SpacetimeDB.TaggedEnum<(DateTimeOffset Time, TimeSpan Interval)> + : SpacetimeDB.TaggedEnum<(TimeSpan Interval, DateTimeOffset Time)> { // Manual expansion of what would be otherwise generated by the [SpacetimeDB.Type] codegen. - public sealed record Time(DateTimeOffset Time_) : ScheduleAt; - public sealed record Interval(TimeSpan Interval_) : ScheduleAt; - public static implicit operator ScheduleAt(DateTimeOffset time) => new Time(time); + public sealed record Time(DateTimeOffset Time_) : ScheduleAt; public static implicit operator ScheduleAt(TimeSpan interval) => new Interval(interval); + public static implicit operator ScheduleAt(DateTimeOffset time) => new Time(time); + public readonly partial struct BSATN : IReadWrite { [SpacetimeDB.Type] private partial record ScheduleAtRepr - : SpacetimeDB.TaggedEnum<(DateTimeOffsetRepr Time, TimeSpanRepr Interval)>; + : SpacetimeDB.TaggedEnum<(TimeSpanRepr Interval, DateTimeOffsetRepr Time)>; private static readonly ScheduleAtRepr.BSATN ReprBSATN = new(); public ScheduleAt Read(BinaryReader reader) => ReprBSATN.Read(reader) switch { - ScheduleAtRepr.Time(var timeRepr) => new Time(timeRepr.ToStd()), ScheduleAtRepr.Interval(var intervalRepr) => new Interval(intervalRepr.ToStd()), + ScheduleAtRepr.Time(var timeRepr) => new Time(timeRepr.ToStd()), _ => throw new SwitchExpressionException(), }; @@ -337,8 +337,8 @@ public void Write(BinaryWriter writer, ScheduleAt value) writer, value switch { - Time(var time) => new ScheduleAtRepr.Time(new(time)), Interval(var interval) => new ScheduleAtRepr.Interval(new(interval)), + Time(var time) => new ScheduleAtRepr.Time(new(time)), _ => throw new SwitchExpressionException(), } ); @@ -349,8 +349,8 @@ public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // to avoid leaking the internal *Repr wrappers in generated SATS. new AlgebraicType.Sum( [ - new("Time", new AlgebraicType.U64(default)), new("Interval", new AlgebraicType.U64(default)), + new("Time", new AlgebraicType.U64(default)), ] ); } diff --git a/crates/sdk/tests/test-client/src/module_bindings/indexed_table_2_table.rs b/crates/sdk/tests/test-client/src/module_bindings/indexed_table_2_table.rs new file mode 100644 index 00000000000..5bfd9233602 --- /dev/null +++ b/crates/sdk/tests/test-client/src/module_bindings/indexed_table_2_table.rs @@ -0,0 +1,91 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. + +#![allow(unused)] +use super::indexed_table_2_type::IndexedTable2; +use spacetimedb_sdk::{ + self as __sdk, + anyhow::{self as __anyhow, Context as _}, + lib as __lib, sats as __sats, ws_messages as __ws, +}; + +/// Table handle for the table `indexed_table_2`. +/// +/// Obtain a handle from the [`IndexedTable2TableAccess::indexed_table_2`] method on [`super::RemoteTables`], +/// like `ctx.db.indexed_table_2()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.indexed_table_2().on_insert(...)`. +pub struct IndexedTable2TableHandle<'ctx> { + imp: __sdk::db_connection::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `indexed_table_2`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait IndexedTable2TableAccess { + #[allow(non_snake_case)] + /// Obtain a [`IndexedTable2TableHandle`], which mediates access to the table `indexed_table_2`. + fn indexed_table_2(&self) -> IndexedTable2TableHandle<'_>; +} + +impl IndexedTable2TableAccess for super::RemoteTables { + fn indexed_table_2(&self) -> IndexedTable2TableHandle<'_> { + IndexedTable2TableHandle { + imp: self.imp.get_table::("indexed_table_2"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct IndexedTable2InsertCallbackId(__sdk::callbacks::CallbackId); +pub struct IndexedTable2DeleteCallbackId(__sdk::callbacks::CallbackId); + +impl<'ctx> __sdk::table::Table for IndexedTable2TableHandle<'ctx> { + type Row = IndexedTable2; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = IndexedTable2InsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> IndexedTable2InsertCallbackId { + IndexedTable2InsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: IndexedTable2InsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = IndexedTable2DeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> IndexedTable2DeleteCallbackId { + IndexedTable2DeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: IndexedTable2DeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, +) -> __anyhow::Result<__sdk::spacetime_module::TableUpdate> { + __sdk::spacetime_module::TableUpdate::parse_table_update_no_primary_key(raw_updates) + .context("Failed to parse table update for table \"indexed_table_2\"") +} diff --git a/crates/sdk/tests/test-client/src/module_bindings/indexed_table_2_type.rs b/crates/sdk/tests/test-client/src/module_bindings/indexed_table_2_type.rs new file mode 100644 index 00000000000..6433317e5ca --- /dev/null +++ b/crates/sdk/tests/test-client/src/module_bindings/indexed_table_2_type.rs @@ -0,0 +1,20 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. + +#![allow(unused)] +use spacetimedb_sdk::{ + self as __sdk, + anyhow::{self as __anyhow, Context as _}, + lib as __lib, sats as __sats, ws_messages as __ws, +}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct IndexedTable2 { + pub player_id: u32, + pub player_snazz: f32, +} + +impl __sdk::spacetime_module::InModule for IndexedTable2 { + type Module = super::RemoteModule; +} diff --git a/crates/sdk/tests/test-client/src/module_bindings/indexed_table_table.rs b/crates/sdk/tests/test-client/src/module_bindings/indexed_table_table.rs new file mode 100644 index 00000000000..35391bdb6fb --- /dev/null +++ b/crates/sdk/tests/test-client/src/module_bindings/indexed_table_table.rs @@ -0,0 +1,91 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. + +#![allow(unused)] +use super::indexed_table_type::IndexedTable; +use spacetimedb_sdk::{ + self as __sdk, + anyhow::{self as __anyhow, Context as _}, + lib as __lib, sats as __sats, ws_messages as __ws, +}; + +/// Table handle for the table `indexed_table`. +/// +/// Obtain a handle from the [`IndexedTableTableAccess::indexed_table`] method on [`super::RemoteTables`], +/// like `ctx.db.indexed_table()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.indexed_table().on_insert(...)`. +pub struct IndexedTableTableHandle<'ctx> { + imp: __sdk::db_connection::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `indexed_table`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait IndexedTableTableAccess { + #[allow(non_snake_case)] + /// Obtain a [`IndexedTableTableHandle`], which mediates access to the table `indexed_table`. + fn indexed_table(&self) -> IndexedTableTableHandle<'_>; +} + +impl IndexedTableTableAccess for super::RemoteTables { + fn indexed_table(&self) -> IndexedTableTableHandle<'_> { + IndexedTableTableHandle { + imp: self.imp.get_table::("indexed_table"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct IndexedTableInsertCallbackId(__sdk::callbacks::CallbackId); +pub struct IndexedTableDeleteCallbackId(__sdk::callbacks::CallbackId); + +impl<'ctx> __sdk::table::Table for IndexedTableTableHandle<'ctx> { + type Row = IndexedTable; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = IndexedTableInsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> IndexedTableInsertCallbackId { + IndexedTableInsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: IndexedTableInsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = IndexedTableDeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> IndexedTableDeleteCallbackId { + IndexedTableDeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: IndexedTableDeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, +) -> __anyhow::Result<__sdk::spacetime_module::TableUpdate> { + __sdk::spacetime_module::TableUpdate::parse_table_update_no_primary_key(raw_updates) + .context("Failed to parse table update for table \"indexed_table\"") +} diff --git a/crates/sdk/tests/test-client/src/module_bindings/indexed_table_type.rs b/crates/sdk/tests/test-client/src/module_bindings/indexed_table_type.rs new file mode 100644 index 00000000000..9f017ff5f8d --- /dev/null +++ b/crates/sdk/tests/test-client/src/module_bindings/indexed_table_type.rs @@ -0,0 +1,19 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. + +#![allow(unused)] +use spacetimedb_sdk::{ + self as __sdk, + anyhow::{self as __anyhow, Context as _}, + lib as __lib, sats as __sats, ws_messages as __ws, +}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct IndexedTable { + pub player_id: u32, +} + +impl __sdk::spacetime_module::InModule for IndexedTable { + type Module = super::RemoteModule; +} diff --git a/crates/sdk/tests/test-client/src/module_bindings/mod.rs b/crates/sdk/tests/test-client/src/module_bindings/mod.rs index 02caa0e57fa..66d78428e7c 100644 --- a/crates/sdk/tests/test-client/src/module_bindings/mod.rs +++ b/crates/sdk/tests/test-client/src/module_bindings/mod.rs @@ -44,6 +44,10 @@ pub mod delete_unique_u_8_reducer; pub mod enum_with_payload_type; pub mod every_primitive_struct_type; pub mod every_vec_struct_type; +pub mod indexed_table_2_table; +pub mod indexed_table_2_type; +pub mod indexed_table_table; +pub mod indexed_table_type; pub mod insert_caller_one_address_reducer; pub mod insert_caller_one_identity_reducer; pub mod insert_caller_pk_address_reducer; @@ -236,6 +240,9 @@ pub mod pk_u_64_table; pub mod pk_u_64_type; pub mod pk_u_8_table; pub mod pk_u_8_type; +pub mod scheduled_table_table; +pub mod scheduled_table_type; +pub mod send_scheduled_message_reducer; pub mod simple_enum_type; pub mod table_holds_table_table; pub mod table_holds_table_type; @@ -389,6 +396,10 @@ pub use delete_unique_u_8_reducer::*; pub use enum_with_payload_type::*; pub use every_primitive_struct_type::*; pub use every_vec_struct_type::*; +pub use indexed_table_2_table::*; +pub use indexed_table_2_type::*; +pub use indexed_table_table::*; +pub use indexed_table_type::*; pub use insert_caller_one_address_reducer::*; pub use insert_caller_one_identity_reducer::*; pub use insert_caller_pk_address_reducer::*; @@ -581,6 +592,9 @@ pub use pk_u_64_table::*; pub use pk_u_64_type::*; pub use pk_u_8_table::*; pub use pk_u_8_type::*; +pub use scheduled_table_table::*; +pub use scheduled_table_type::*; +pub use send_scheduled_message_reducer::*; pub use simple_enum_type::*; pub use table_holds_table_table::*; pub use table_holds_table_type::*; @@ -837,6 +851,7 @@ pub enum Reducer { InsertVecU8(insert_vec_u_8_reducer::InsertVecU8), InsertVecUnitStruct(insert_vec_unit_struct_reducer::InsertVecUnitStruct), NoOpSucceeds(no_op_succeeds_reducer::NoOpSucceeds), + SendScheduledMessage(send_scheduled_message_reducer::SendScheduledMessage), UpdatePkAddress(update_pk_address_reducer::UpdatePkAddress), UpdatePkBool(update_pk_bool_reducer::UpdatePkBool), UpdatePkI128(update_pk_i_128_reducer::UpdatePkI128), @@ -1008,6 +1023,7 @@ impl __sdk::spacetime_module::Reducer for Reducer { Reducer::InsertVecU8(_) => "insert_vec_u8", Reducer::InsertVecUnitStruct(_) => "insert_vec_unit_struct", Reducer::NoOpSucceeds(_) => "no_op_succeeds", + Reducer::SendScheduledMessage(_) => "send_scheduled_message", Reducer::UpdatePkAddress(_) => "update_pk_address", Reducer::UpdatePkBool(_) => "update_pk_bool", Reducer::UpdatePkI128(_) => "update_pk_i128", @@ -1174,6 +1190,7 @@ impl __sdk::spacetime_module::Reducer for Reducer { Reducer::InsertVecU8(args) => args, Reducer::InsertVecUnitStruct(args) => args, Reducer::NoOpSucceeds(args) => args, + Reducer::SendScheduledMessage(args) => args, Reducer::UpdatePkAddress(args) => args, Reducer::UpdatePkBool(args) => args, Reducer::UpdatePkI128(args) => args, @@ -1700,6 +1717,9 @@ impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer { "no_op_succeeds", &value.args, )?)), + "send_scheduled_message" => Ok(Reducer::SendScheduledMessage( + __sdk::spacetime_module::parse_reducer_args("send_scheduled_message", &value.args)?, + )), "update_pk_address" => Ok(Reducer::UpdatePkAddress(__sdk::spacetime_module::parse_reducer_args( "update_pk_address", &value.args, @@ -1834,6 +1854,8 @@ impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer { #[allow(non_snake_case)] #[doc(hidden)] pub struct DbUpdate { + indexed_table: __sdk::spacetime_module::TableUpdate, + indexed_table_2: __sdk::spacetime_module::TableUpdate, large_table: __sdk::spacetime_module::TableUpdate, one_address: __sdk::spacetime_module::TableUpdate, one_bool: __sdk::spacetime_module::TableUpdate, @@ -1881,6 +1903,7 @@ pub struct DbUpdate { pk_u_32: __sdk::spacetime_module::TableUpdate, pk_u_64: __sdk::spacetime_module::TableUpdate, pk_u_8: __sdk::spacetime_module::TableUpdate, + scheduled_table: __sdk::spacetime_module::TableUpdate, table_holds_table: __sdk::spacetime_module::TableUpdate, unique_address: __sdk::spacetime_module::TableUpdate, unique_bool: __sdk::spacetime_module::TableUpdate, @@ -1930,6 +1953,10 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate { let mut db_update = DbUpdate::default(); for table_update in raw.tables { match &table_update.table_name[..] { + "indexed_table" => db_update.indexed_table = indexed_table_table::parse_table_update(table_update)?, + "indexed_table_2" => { + db_update.indexed_table_2 = indexed_table_2_table::parse_table_update(table_update)? + } "large_table" => db_update.large_table = large_table_table::parse_table_update(table_update)?, "one_address" => db_update.one_address = one_address_table::parse_table_update(table_update)?, "one_bool" => db_update.one_bool = one_bool_table::parse_table_update(table_update)?, @@ -1999,6 +2026,9 @@ impl TryFrom<__ws::DatabaseUpdate<__ws::BsatnFormat>> for DbUpdate { "pk_u32" => db_update.pk_u_32 = pk_u_32_table::parse_table_update(table_update)?, "pk_u64" => db_update.pk_u_64 = pk_u_64_table::parse_table_update(table_update)?, "pk_u8" => db_update.pk_u_8 = pk_u_8_table::parse_table_update(table_update)?, + "scheduled_table" => { + db_update.scheduled_table = scheduled_table_table::parse_table_update(table_update)? + } "table_holds_table" => { db_update.table_holds_table = table_holds_table_table::parse_table_update(table_update)? } @@ -2071,6 +2101,8 @@ impl __sdk::spacetime_module::InModule for DbUpdate { impl __sdk::spacetime_module::DbUpdate for DbUpdate { fn apply_to_client_cache(&self, cache: &mut __sdk::client_cache::ClientCache) { + cache.apply_diff_to_table::("indexed_table", &self.indexed_table); + cache.apply_diff_to_table::("indexed_table_2", &self.indexed_table_2); cache.apply_diff_to_table::("large_table", &self.large_table); cache.apply_diff_to_table::("one_address", &self.one_address); cache.apply_diff_to_table::("one_bool", &self.one_bool); @@ -2124,6 +2156,7 @@ impl __sdk::spacetime_module::DbUpdate for DbUpdate { cache.apply_diff_to_table::("pk_u32", &self.pk_u_32); cache.apply_diff_to_table::("pk_u64", &self.pk_u_64); cache.apply_diff_to_table::("pk_u8", &self.pk_u_8); + cache.apply_diff_to_table::("scheduled_table", &self.scheduled_table); cache.apply_diff_to_table::("table_holds_table", &self.table_holds_table); cache.apply_diff_to_table::("unique_address", &self.unique_address); cache.apply_diff_to_table::("unique_bool", &self.unique_bool); @@ -2170,6 +2203,8 @@ impl __sdk::spacetime_module::DbUpdate for DbUpdate { cache.apply_diff_to_table::("vec_unit_struct", &self.vec_unit_struct); } fn invoke_row_callbacks(&self, event: &EventContext, callbacks: &mut __sdk::callbacks::DbCallbacks) { + callbacks.invoke_table_row_callbacks::("indexed_table", &self.indexed_table, event); + callbacks.invoke_table_row_callbacks::("indexed_table_2", &self.indexed_table_2, event); callbacks.invoke_table_row_callbacks::("large_table", &self.large_table, event); callbacks.invoke_table_row_callbacks::("one_address", &self.one_address, event); callbacks.invoke_table_row_callbacks::("one_bool", &self.one_bool, event); @@ -2237,6 +2272,7 @@ impl __sdk::spacetime_module::DbUpdate for DbUpdate { callbacks.invoke_table_row_callbacks::("pk_u32", &self.pk_u_32, event); callbacks.invoke_table_row_callbacks::("pk_u64", &self.pk_u_64, event); callbacks.invoke_table_row_callbacks::("pk_u8", &self.pk_u_8, event); + callbacks.invoke_table_row_callbacks::("scheduled_table", &self.scheduled_table, event); callbacks.invoke_table_row_callbacks::("table_holds_table", &self.table_holds_table, event); callbacks.invoke_table_row_callbacks::("unique_address", &self.unique_address, event); callbacks.invoke_table_row_callbacks::("unique_bool", &self.unique_bool, event); diff --git a/crates/sdk/tests/test-client/src/module_bindings/scheduled_table_table.rs b/crates/sdk/tests/test-client/src/module_bindings/scheduled_table_table.rs new file mode 100644 index 00000000000..fae671ee9b5 --- /dev/null +++ b/crates/sdk/tests/test-client/src/module_bindings/scheduled_table_table.rs @@ -0,0 +1,143 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. + +#![allow(unused)] +use super::scheduled_table_type::ScheduledTable; +use spacetimedb_sdk::{ + self as __sdk, + anyhow::{self as __anyhow, Context as _}, + lib as __lib, sats as __sats, ws_messages as __ws, +}; + +/// Table handle for the table `scheduled_table`. +/// +/// Obtain a handle from the [`ScheduledTableTableAccess::scheduled_table`] method on [`super::RemoteTables`], +/// like `ctx.db.scheduled_table()`. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.scheduled_table().on_insert(...)`. +pub struct ScheduledTableTableHandle<'ctx> { + imp: __sdk::db_connection::TableHandle, + ctx: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +#[allow(non_camel_case_types)] +/// Extension trait for access to the table `scheduled_table`. +/// +/// Implemented for [`super::RemoteTables`]. +pub trait ScheduledTableTableAccess { + #[allow(non_snake_case)] + /// Obtain a [`ScheduledTableTableHandle`], which mediates access to the table `scheduled_table`. + fn scheduled_table(&self) -> ScheduledTableTableHandle<'_>; +} + +impl ScheduledTableTableAccess for super::RemoteTables { + fn scheduled_table(&self) -> ScheduledTableTableHandle<'_> { + ScheduledTableTableHandle { + imp: self.imp.get_table::("scheduled_table"), + ctx: std::marker::PhantomData, + } + } +} + +pub struct ScheduledTableInsertCallbackId(__sdk::callbacks::CallbackId); +pub struct ScheduledTableDeleteCallbackId(__sdk::callbacks::CallbackId); + +impl<'ctx> __sdk::table::Table for ScheduledTableTableHandle<'ctx> { + type Row = ScheduledTable; + type EventContext = super::EventContext; + + fn count(&self) -> u64 { + self.imp.count() + } + fn iter(&self) -> impl Iterator + '_ { + self.imp.iter() + } + + type InsertCallbackId = ScheduledTableInsertCallbackId; + + fn on_insert( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> ScheduledTableInsertCallbackId { + ScheduledTableInsertCallbackId(self.imp.on_insert(Box::new(callback))) + } + + fn remove_on_insert(&self, callback: ScheduledTableInsertCallbackId) { + self.imp.remove_on_insert(callback.0) + } + + type DeleteCallbackId = ScheduledTableDeleteCallbackId; + + fn on_delete( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row) + Send + 'static, + ) -> ScheduledTableDeleteCallbackId { + ScheduledTableDeleteCallbackId(self.imp.on_delete(Box::new(callback))) + } + + fn remove_on_delete(&self, callback: ScheduledTableDeleteCallbackId) { + self.imp.remove_on_delete(callback.0) + } +} + +pub struct ScheduledTableUpdateCallbackId(__sdk::callbacks::CallbackId); + +impl<'ctx> __sdk::table::TableWithPrimaryKey for ScheduledTableTableHandle<'ctx> { + type UpdateCallbackId = ScheduledTableUpdateCallbackId; + + fn on_update( + &self, + callback: impl FnMut(&Self::EventContext, &Self::Row, &Self::Row) + Send + 'static, + ) -> ScheduledTableUpdateCallbackId { + ScheduledTableUpdateCallbackId(self.imp.on_update(Box::new(callback))) + } + + fn remove_on_update(&self, callback: ScheduledTableUpdateCallbackId) { + self.imp.remove_on_update(callback.0) + } +} + +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, +) -> __anyhow::Result<__sdk::spacetime_module::TableUpdate> { + __sdk::spacetime_module::TableUpdate::parse_table_update_with_primary_key::( + raw_updates, + |row: &ScheduledTable| &row.scheduled_id, + ) + .context("Failed to parse table update for table \"scheduled_table\"") +} + +/// Access to the `scheduled_id` unique index on the table `scheduled_table`, +/// which allows point queries on the field of the same name +/// via the [`ScheduledTableScheduledIdUnique::find`] method. +/// +/// Users are encouraged not to explicitly reference this type, +/// but to directly chain method calls, +/// like `ctx.db.scheduled_table().scheduled_id().find(...)`. +pub struct ScheduledTableScheduledIdUnique<'ctx> { + imp: __sdk::client_cache::UniqueConstraint, + phantom: std::marker::PhantomData<&'ctx super::RemoteTables>, +} + +impl<'ctx> ScheduledTableTableHandle<'ctx> { + /// Get a handle on the `scheduled_id` unique index on the table `scheduled_table`. + pub fn scheduled_id(&self) -> ScheduledTableScheduledIdUnique<'ctx> { + ScheduledTableScheduledIdUnique { + imp: self + .imp + .get_unique_constraint::("scheduled_id", |row| &row.scheduled_id), + phantom: std::marker::PhantomData, + } + } +} + +impl<'ctx> ScheduledTableScheduledIdUnique<'ctx> { + /// Find the subscribed row whose `scheduled_id` column value is equal to `col_val`, + /// if such a row is present in the client cache. + pub fn find(&self, col_val: &u64) -> Option { + self.imp.find(col_val) + } +} diff --git a/crates/sdk/tests/test-client/src/module_bindings/scheduled_table_type.rs b/crates/sdk/tests/test-client/src/module_bindings/scheduled_table_type.rs new file mode 100644 index 00000000000..45f93e2365e --- /dev/null +++ b/crates/sdk/tests/test-client/src/module_bindings/scheduled_table_type.rs @@ -0,0 +1,21 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. + +#![allow(unused)] +use spacetimedb_sdk::{ + self as __sdk, + anyhow::{self as __anyhow, Context as _}, + lib as __lib, sats as __sats, ws_messages as __ws, +}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct ScheduledTable { + pub text: String, + pub scheduled_id: u64, + pub scheduled_at: __sdk::ScheduleAt, +} + +impl __sdk::spacetime_module::InModule for ScheduledTable { + type Module = super::RemoteModule; +} diff --git a/crates/sdk/tests/test-client/src/module_bindings/send_scheduled_message_reducer.rs b/crates/sdk/tests/test-client/src/module_bindings/send_scheduled_message_reducer.rs new file mode 100644 index 00000000000..4ef2cd4a49a --- /dev/null +++ b/crates/sdk/tests/test-client/src/module_bindings/send_scheduled_message_reducer.rs @@ -0,0 +1,93 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. + +#![allow(unused)] +use spacetimedb_sdk::{ + self as __sdk, + anyhow::{self as __anyhow, Context as _}, + lib as __lib, sats as __sats, ws_messages as __ws, +}; + +use super::scheduled_table_type::ScheduledTable; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct SendScheduledMessage { + pub arg: ScheduledTable, +} + +impl __sdk::spacetime_module::InModule for SendScheduledMessage { + type Module = super::RemoteModule; +} + +pub struct SendScheduledMessageCallbackId(__sdk::callbacks::CallbackId); + +#[allow(non_camel_case_types)] +/// Extension trait for access to the reducer `send_scheduled_message`. +/// +/// Implemented for [`super::RemoteReducers`]. +pub trait send_scheduled_message { + /// Request that the remote module invoke the reducer `send_scheduled_message` to run as soon as possible. + /// + /// This method returns immediately, and errors only if we are unable to send the request. + /// The reducer will run asynchronously in the future, + /// and its status can be observed by listening for [`Self::on_send_scheduled_message`] callbacks. + fn send_scheduled_message(&self, arg: ScheduledTable) -> __anyhow::Result<()>; + /// Register a callback to run whenever we are notified of an invocation of the reducer `send_scheduled_message`. + /// + /// The [`super::EventContext`] passed to the `callback` + /// will always have [`__sdk::Event::Reducer`] as its `event`, + /// but it may or may not have terminated successfully and been committed. + /// Callbacks should inspect the [`__sdk::ReducerEvent`] contained in the [`super::EventContext`] + /// to determine the reducer's status. + /// + /// The returned [`SendScheduledMessageCallbackId`] can be passed to [`Self::remove_on_send_scheduled_message`] + /// to cancel the callback. + fn on_send_scheduled_message( + &self, + callback: impl FnMut(&super::EventContext, &ScheduledTable) + Send + 'static, + ) -> SendScheduledMessageCallbackId; + /// Cancel a callback previously registered by [`Self::on_send_scheduled_message`], + /// causing it not to run in the future. + fn remove_on_send_scheduled_message(&self, callback: SendScheduledMessageCallbackId); +} + +impl send_scheduled_message for super::RemoteReducers { + fn send_scheduled_message(&self, arg: ScheduledTable) -> __anyhow::Result<()> { + self.imp + .call_reducer("send_scheduled_message", SendScheduledMessage { arg }) + } + fn on_send_scheduled_message( + &self, + mut callback: impl FnMut(&super::EventContext, &ScheduledTable) + Send + 'static, + ) -> SendScheduledMessageCallbackId { + SendScheduledMessageCallbackId(self.imp.on_reducer::( + "send_scheduled_message", + Box::new(move |ctx: &super::EventContext, args: &SendScheduledMessage| callback(ctx, &args.arg)), + )) + } + fn remove_on_send_scheduled_message(&self, callback: SendScheduledMessageCallbackId) { + self.imp + .remove_on_reducer::("send_scheduled_message", callback.0) + } +} + +#[allow(non_camel_case_types)] +#[doc(hidden)] +/// Extension trait for setting the call-flags for the reducer `send_scheduled_message`. +/// +/// Implemented for [`super::SetReducerFlags`]. +/// +/// This type is currently unstable and may be removed without a major version bump. +pub trait set_flags_for_send_scheduled_message { + /// Set the call-reducer flags for the reducer `send_scheduled_message` to `flags`. + /// + /// This type is currently unstable and may be removed without a major version bump. + fn send_scheduled_message(&self, flags: __ws::CallReducerFlags); +} + +impl set_flags_for_send_scheduled_message for super::SetReducerFlags { + fn send_scheduled_message(&self, flags: __ws::CallReducerFlags) { + self.imp.set_call_reducer_flags("send_scheduled_message", flags); + } +} diff --git a/modules/sdk-test-cs/Lib.cs b/modules/sdk-test-cs/Lib.cs index 670e639024d..58ae3736cf8 100644 --- a/modules/sdk-test-cs/Lib.cs +++ b/modules/sdk-test-cs/Lib.cs @@ -1713,7 +1713,8 @@ public static void insert_large_table( EveryVecStruct v ) { - ctx.Db.large_table.Insert(new LargeTable { + ctx.Db.large_table.Insert(new LargeTable + { a = a, b = b, c = c, @@ -1742,7 +1743,8 @@ EveryVecStruct v [SpacetimeDB.Reducer] public static void insert_primitives_as_strings(ReducerContext ctx, EveryPrimitiveStruct s) { - ctx.Db.vec_string.Insert(new VecString { + ctx.Db.vec_string.Insert(new VecString + { s = typeof(EveryPrimitiveStruct) .GetFields() .Select(f => f.GetValue(s)!.ToString()!.ToLowerInvariant()) @@ -1765,4 +1767,33 @@ public static void insert_table_holds_table(ReducerContext ctx, OneU8 a, VecU8 b [SpacetimeDB.Reducer] public static void no_op_succeeds(ReducerContext ctx) { } + + [SpacetimeDB.Table(Name = "scheduled_table", Scheduled = nameof(send_scheduled_message))] + public partial struct ScheduledTable + { + public string text; + } + + [SpacetimeDB.Reducer] + public static void send_scheduled_message(ReducerContext ctx, ScheduledTable arg) + { + ulong id = arg.ScheduledId; + SpacetimeDB.ScheduleAt scheduleAt = arg.ScheduledAt; + string text = arg.text; + } + + [SpacetimeDB.Table(Name = "indexed_table")] + [SpacetimeDB.Index(Name = "player_id_index", BTree = [nameof(player_id)])] + public partial struct IndexedTable + { + uint player_id; + } + + [SpacetimeDB.Table(Name = "indexed_table_2")] + [SpacetimeDB.Index(Name = "player_id_snazz_index", BTree = [nameof(player_id), nameof(player_snazz)])] + public partial struct IndexedTable2 + { + uint player_id; + float player_snazz; + } } diff --git a/modules/sdk-test/src/lib.rs b/modules/sdk-test/src/lib.rs index c370b65dc3c..2ea9c99749e 100644 --- a/modules/sdk-test/src/lib.rs +++ b/modules/sdk-test/src/lib.rs @@ -641,3 +641,26 @@ define_tables! { fn no_op_succeeds(_ctx: &ReducerContext) {} spacetimedb::filter!("SELECT * FROM one_u8"); + +#[spacetimedb::table(name = scheduled_table, scheduled(send_scheduled_message), public)] +pub struct ScheduledTable { + text: String, +} + +#[spacetimedb::reducer] +fn send_scheduled_message(_ctx: &ReducerContext, arg: ScheduledTable) { + let _ = arg.text; + let _ = arg.scheduled_at; + let _ = arg.scheduled_id; +} + +#[spacetimedb::table(name = indexed_table, index(name=player_id_index, btree(columns = [player_id])))] +struct IndexedTable { + player_id: u32, +} + +#[spacetimedb::table(name = indexed_table_2, index(name=player_id_snazz_index, btree(columns = [player_id, player_snazz])))] +struct IndexedTable2 { + player_id: u32, + player_snazz: f32, +} From 6b075f89f459ba21978e7199a302d4835184365e Mon Sep 17 00:00:00 2001 From: James Gilles Date: Fri, 22 Nov 2024 15:36:44 -0500 Subject: [PATCH 2/2] Update to comply with new requirements --- modules/sdk-test/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/sdk-test/src/lib.rs b/modules/sdk-test/src/lib.rs index 2ea9c99749e..33e20834f85 100644 --- a/modules/sdk-test/src/lib.rs +++ b/modules/sdk-test/src/lib.rs @@ -9,7 +9,7 @@ use anyhow::{Context, Result}; use spacetimedb::{ sats::{i256, u256}, - Address, Identity, ReducerContext, SpacetimeType, Table, + Address, Identity, ReducerContext, ScheduleAt, SpacetimeType, Table, }; #[derive(SpacetimeType)] @@ -645,6 +645,11 @@ spacetimedb::filter!("SELECT * FROM one_u8"); #[spacetimedb::table(name = scheduled_table, scheduled(send_scheduled_message), public)] pub struct ScheduledTable { text: String, + #[primary_key] + #[auto_inc] + scheduled_id: u64, + #[scheduled_at] + scheduled_at: ScheduleAt, } #[spacetimedb::reducer]