From df966e9ae014af7258634f8b941502dbc062c124 Mon Sep 17 00:00:00 2001 From: James Gilles Date: Thu, 21 Nov 2024 16:39:39 -0500 Subject: [PATCH 1/3] 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 | 94 ++++++++++++ .../module_bindings/indexed_table_2_type.rs | 19 +++ .../module_bindings/indexed_table_table.rs | 94 ++++++++++++ .../src/module_bindings/indexed_table_type.rs | 18 +++ .../test-client/src/module_bindings/mod.rs | 43 ++++++ .../module_bindings/scheduled_table_table.rs | 144 ++++++++++++++++++ .../module_bindings/scheduled_table_type.rs | 20 +++ .../send_scheduled_message_reducer.rs | 110 +++++++++++++ modules/sdk-test-cs/Lib.cs | 35 ++++- modules/sdk-test/src/lib.rs | 28 ++++ 11 files changed, 611 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..1fa90b9aab6 --- /dev/null +++ b/crates/sdk/tests/test-client/src/module_bindings/indexed_table_2_table.rs @@ -0,0 +1,94 @@ +// 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::__codegen::{ + self as __sdk, __lib, __sats, __ws, + anyhow::{self as __anyhow, Context as _}, +}; + +/// 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::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::CallbackId); +pub struct IndexedTable2DeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::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 register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("indexed_table_2"); +} +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, +) -> __anyhow::Result<__sdk::TableUpdate> { + __sdk::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..ffcb7ba9cd9 --- /dev/null +++ b/crates/sdk/tests/test-client/src/module_bindings/indexed_table_2_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::__codegen::{ + self as __sdk, __lib, __sats, __ws, + anyhow::{self as __anyhow, Context as _}, +}; + +#[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::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..2e5e209fec8 --- /dev/null +++ b/crates/sdk/tests/test-client/src/module_bindings/indexed_table_table.rs @@ -0,0 +1,94 @@ +// 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::__codegen::{ + self as __sdk, __lib, __sats, __ws, + anyhow::{self as __anyhow, Context as _}, +}; + +/// 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::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::CallbackId); +pub struct IndexedTableDeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::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 register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("indexed_table"); +} +#[doc(hidden)] +pub(super) fn parse_table_update( + raw_updates: __ws::TableUpdate<__ws::BsatnFormat>, +) -> __anyhow::Result<__sdk::TableUpdate> { + __sdk::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..91e70cc981c --- /dev/null +++ b/crates/sdk/tests/test-client/src/module_bindings/indexed_table_type.rs @@ -0,0 +1,18 @@ +// 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::__codegen::{ + self as __sdk, __lib, __sats, __ws, + anyhow::{self as __anyhow, Context as _}, +}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct IndexedTable { + pub player_id: u32, +} + +impl __sdk::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 e048a98bbe2..fc8679bca92 100644 --- a/crates/sdk/tests/test-client/src/module_bindings/mod.rs +++ b/crates/sdk/tests/test-client/src/module_bindings/mod.rs @@ -43,6 +43,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; @@ -235,6 +239,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; @@ -406,6 +413,10 @@ pub use delete_unique_u_8_reducer::{delete_unique_u_8, set_flags_for_delete_uniq pub use enum_with_payload_type::EnumWithPayload; pub use every_primitive_struct_type::EveryPrimitiveStruct; pub use every_vec_struct_type::EveryVecStruct; +pub use indexed_table_2_table::*; +pub use indexed_table_2_type::IndexedTable2; +pub use indexed_table_table::*; +pub use indexed_table_type::IndexedTable; pub use insert_caller_one_address_reducer::{ insert_caller_one_address, set_flags_for_insert_caller_one_address, InsertCallerOneAddressCallbackId, }; @@ -683,6 +694,11 @@ pub use pk_u_64_table::*; pub use pk_u_64_type::PkU64; pub use pk_u_8_table::*; pub use pk_u_8_type::PkU8; +pub use scheduled_table_table::*; +pub use scheduled_table_type::ScheduledTable; +pub use send_scheduled_message_reducer::{ + send_scheduled_message, set_flags_for_send_scheduled_message, SendScheduledMessageCallbackId, +}; pub use simple_enum_type::SimpleEnum; pub use table_holds_table_table::*; pub use table_holds_table_type::TableHoldsTable; @@ -1260,6 +1276,9 @@ pub enum Reducer { s: Vec, }, NoOpSucceeds, + SendScheduledMessage { + arg: ScheduledTable, + }, UpdatePkAddress { a: __sdk::Address, data: i32, @@ -1527,6 +1546,7 @@ impl __sdk::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", @@ -2281,6 +2301,10 @@ impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer { &value.args, )? .into()), + "send_scheduled_message" => Ok(__sdk::parse_reducer_args::< + send_scheduled_message_reducer::SendScheduledMessageArgs, + >("send_scheduled_message", &value.args)? + .into()), "update_pk_address" => Ok( __sdk::parse_reducer_args::( "update_pk_address", @@ -2479,6 +2503,8 @@ impl TryFrom<__ws::ReducerCallInfo<__ws::BsatnFormat>> for Reducer { #[allow(non_snake_case)] #[doc(hidden)] pub struct DbUpdate { + indexed_table: __sdk::TableUpdate, + indexed_table_2: __sdk::TableUpdate, large_table: __sdk::TableUpdate, one_address: __sdk::TableUpdate, one_bool: __sdk::TableUpdate, @@ -2526,6 +2552,7 @@ pub struct DbUpdate { pk_u_32: __sdk::TableUpdate, pk_u_64: __sdk::TableUpdate, pk_u_8: __sdk::TableUpdate, + scheduled_table: __sdk::TableUpdate, table_holds_table: __sdk::TableUpdate, unique_address: __sdk::TableUpdate, unique_bool: __sdk::TableUpdate, @@ -2575,6 +2602,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)?, @@ -2644,6 +2675,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)? } @@ -2716,6 +2750,8 @@ impl __sdk::InModule for DbUpdate { impl __sdk::DbUpdate for DbUpdate { fn apply_to_client_cache(&self, cache: &mut __sdk::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); @@ -2769,6 +2805,7 @@ impl __sdk::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); @@ -2815,6 +2852,8 @@ impl __sdk::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::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); @@ -2882,6 +2921,7 @@ impl __sdk::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); @@ -3258,6 +3298,8 @@ impl __sdk::SpacetimeModule for RemoteModule { type SubscriptionHandle = SubscriptionHandle; fn register_tables(client_cache: &mut __sdk::ClientCache) { + indexed_table_table::register_table(client_cache); + indexed_table_2_table::register_table(client_cache); large_table_table::register_table(client_cache); one_address_table::register_table(client_cache); one_bool_table::register_table(client_cache); @@ -3305,6 +3347,7 @@ impl __sdk::SpacetimeModule for RemoteModule { pk_u_32_table::register_table(client_cache); pk_u_64_table::register_table(client_cache); pk_u_8_table::register_table(client_cache); + scheduled_table_table::register_table(client_cache); table_holds_table_table::register_table(client_cache); unique_address_table::register_table(client_cache); unique_bool_table::register_table(client_cache); 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..cd9cf2faeda --- /dev/null +++ b/crates/sdk/tests/test-client/src/module_bindings/scheduled_table_table.rs @@ -0,0 +1,144 @@ +// 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::__codegen::{ + self as __sdk, __lib, __sats, __ws, + anyhow::{self as __anyhow, Context as _}, +}; + +/// 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::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::CallbackId); +pub struct ScheduledTableDeleteCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::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) + } +} + +#[doc(hidden)] +pub(super) fn register_table(client_cache: &mut __sdk::ClientCache) { + let _table = client_cache.get_or_make_table::("scheduled_table"); + _table.add_unique_constraint::("scheduled_id", |row| &row.scheduled_id); +} +pub struct ScheduledTableUpdateCallbackId(__sdk::CallbackId); + +impl<'ctx> __sdk::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::TableUpdate> { + __sdk::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::UniqueConstraintHandle, + 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"), + 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..2d2b4433987 --- /dev/null +++ b/crates/sdk/tests/test-client/src/module_bindings/scheduled_table_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::__codegen::{ + self as __sdk, __lib, __sats, __ws, + anyhow::{self as __anyhow, Context as _}, +}; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub struct ScheduledTable { + pub scheduled_id: u64, + pub scheduled_at: __sdk::ScheduleAt, + pub text: String, +} + +impl __sdk::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..d78e550ce2e --- /dev/null +++ b/crates/sdk/tests/test-client/src/module_bindings/send_scheduled_message_reducer.rs @@ -0,0 +1,110 @@ +// 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::__codegen::{ + self as __sdk, __lib, __sats, __ws, + anyhow::{self as __anyhow, Context as _}, +}; + +use super::scheduled_table_type::ScheduledTable; + +#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)] +#[sats(crate = __lib)] +pub(super) struct SendScheduledMessageArgs { + pub arg: ScheduledTable, +} + +impl From for super::Reducer { + fn from(args: SendScheduledMessageArgs) -> Self { + Self::SendScheduledMessage { arg: args.arg } + } +} + +impl __sdk::InModule for SendScheduledMessageArgs { + type Module = super::RemoteModule; +} + +pub struct SendScheduledMessageCallbackId(__sdk::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", SendScheduledMessageArgs { 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| { + let super::EventContext { + event: + __sdk::Event::Reducer(__sdk::ReducerEvent { + reducer: super::Reducer::SendScheduledMessage { arg }, + .. + }), + .. + } = ctx + else { + unreachable!() + }; + callback(ctx, 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..529b160f5fb 100644 --- a/modules/sdk-test/src/lib.rs +++ b/modules/sdk-test/src/lib.rs @@ -641,3 +641,31 @@ 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 { + #[primary_key] + #[auto_inc] + scheduled_id: u64, + #[scheduled_at] + scheduled_at: spacetimedb::ScheduleAt, + 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 62cbd0733790d8a03ca117078806aa0fb1c960ef Mon Sep 17 00:00:00 2001 From: James Gilles Date: Fri, 22 Nov 2024 15:36:44 -0500 Subject: [PATCH 2/3] 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 529b160f5fb..1906aaefde1 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)] @@ -650,6 +650,11 @@ pub struct ScheduledTable { #[scheduled_at] scheduled_at: spacetimedb::ScheduleAt, text: String, + #[primary_key] + #[auto_inc] + scheduled_id: u64, + #[scheduled_at] + scheduled_at: ScheduleAt, } #[spacetimedb::reducer] From 476dc6fac6a92b8a106f98a37aa9772f007557be Mon Sep 17 00:00:00 2001 From: Tyler Cloutier Date: Mon, 9 Dec 2024 23:51:17 -0500 Subject: [PATCH 3/3] Fixed weird compile bug --- modules/sdk-test/src/lib.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/modules/sdk-test/src/lib.rs b/modules/sdk-test/src/lib.rs index 1906aaefde1..529b160f5fb 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, ScheduleAt, SpacetimeType, Table, + Address, Identity, ReducerContext, SpacetimeType, Table, }; #[derive(SpacetimeType)] @@ -650,11 +650,6 @@ pub struct ScheduledTable { #[scheduled_at] scheduled_at: spacetimedb::ScheduleAt, text: String, - #[primary_key] - #[auto_inc] - scheduled_id: u64, - #[scheduled_at] - scheduled_at: ScheduleAt, } #[spacetimedb::reducer]