Skip to content

Commit ac0053c

Browse files
Centrilgefjon
andauthored
Websocket API: Light transaction updates & NoSuccessNotify (#1812)
Signed-off-by: Mazdak Farrokhzad <[email protected]> Co-authored-by: Phoebe Goldman <[email protected]>
1 parent 1657fd2 commit ac0053c

File tree

195 files changed

+4401
-186
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

195 files changed

+4401
-186
lines changed

crates/cli/src/subcommands/generate/csharp.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ fn default_init(ctx: &GenCtx, ty: &AlgebraicType) -> Option<&'static str> {
9494
AlgebraicType::Sum(sum_type) if sum_type.is_option() || sum_type.is_simple_enum() => None,
9595
// TODO: generate some proper default here (what would it be for tagged enums?).
9696
AlgebraicType::Sum(_) => Some("null!"),
97-
// For product types, arrays, and maps, we can use the default constructor.
97+
// For product types and arrays, we can use the default constructor.
9898
AlgebraicType::Product(_) | AlgebraicType::Array(_) => Some("new()"),
9999
// Strings must have explicit default value of "".
100100
AlgebraicType::String => Some(r#""""#),
@@ -641,7 +641,11 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
641641

642642
writeln!(output, "public sealed class RemoteReducers : RemoteBase<DbConnection>");
643643
indented_block(&mut output, |output| {
644-
writeln!(output, "internal RemoteReducers(DbConnection conn) : base(conn) {{}}");
644+
writeln!(
645+
output,
646+
"internal RemoteReducers(DbConnection conn, SetReducerFlags SetReducerFlags) : base(conn) {{ this.SetCallReducerFlags = SetReducerFlags; }}"
647+
);
648+
writeln!(output, "internal readonly SetReducerFlags SetCallReducerFlags;");
645649

646650
for reducer in &reducers {
647651
let func_name = &*reducer.name;
@@ -683,7 +687,7 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
683687
indented_block(output, |output| {
684688
writeln!(
685689
output,
686-
"conn.InternalCallReducer(new {func_name_pascal_case} {{ {field_inits} }});"
690+
"conn.InternalCallReducer(new {func_name_pascal_case} {{ {field_inits} }}, this.SetCallReducerFlags.{func_name_pascal_case}Flags);"
687691
);
688692
});
689693
writeln!(output);
@@ -716,12 +720,25 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
716720
});
717721
writeln!(output);
718722

723+
writeln!(output, "public sealed class SetReducerFlags");
724+
indented_block(&mut output, |output| {
725+
writeln!(output, "internal SetReducerFlags() {{ }}");
726+
for reducer in &reducers {
727+
let func_name = &*reducer.name;
728+
let func_name_pascal_case = func_name.to_case(Case::Pascal);
729+
writeln!(output, "internal CallReducerFlags {func_name_pascal_case}Flags;");
730+
writeln!(output, "public void {func_name_pascal_case}(CallReducerFlags flags) {{ this.{func_name_pascal_case}Flags = flags; }}");
731+
}
732+
});
733+
writeln!(output);
734+
719735
writeln!(
720736
output,
721737
"public partial record EventContext : DbContext<RemoteTables>, IEventContext"
722738
);
723739
indented_block(&mut output, |output| {
724740
writeln!(output, "public readonly RemoteReducers Reducers;");
741+
writeln!(output, "public readonly SetReducerFlags SetReducerFlags;");
725742
writeln!(output, "public readonly Event<Reducer> Event;");
726743
writeln!(output);
727744
writeln!(
@@ -730,6 +747,7 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
730747
);
731748
indented_block(output, |output| {
732749
writeln!(output, "Reducers = conn.Reducers;");
750+
writeln!(output, "SetReducerFlags = conn.SetReducerFlags;");
733751
writeln!(output, "Event = reducerEvent;");
734752
});
735753
});
@@ -755,11 +773,13 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
755773
indented_block(&mut output, |output| {
756774
writeln!(output, "public readonly RemoteTables Db = new();");
757775
writeln!(output, "public readonly RemoteReducers Reducers;");
776+
writeln!(output, "public readonly SetReducerFlags SetReducerFlags;");
758777
writeln!(output);
759778

760779
writeln!(output, "public DbConnection()");
761780
indented_block(output, |output| {
762-
writeln!(output, "Reducers = new(this);");
781+
writeln!(output, "SetReducerFlags = new();");
782+
writeln!(output, "Reducers = new(this, this.SetReducerFlags);");
763783
writeln!(output);
764784

765785
for item in items {

crates/cli/src/subcommands/generate/rust.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ Requested namespace: {namespace}",
339339

340340
let reducer_name = reducer.name.deref();
341341
let func_name = reducer_function_name(reducer);
342+
let set_reducer_flags_trait = format!("set_flags_for_{func_name}");
342343
let args_type = reducer_args_type_name(&reducer.name);
343344

344345
define_struct_for_product(module, out, &args_type, &reducer.params_for_generate.elements);
@@ -431,6 +432,26 @@ impl {func_name} for super::RemoteReducers {{
431432
self.imp.remove_on_reducer::<{args_type}>({reducer_name:?}, callback.0)
432433
}}
433434
}}
435+
436+
#[allow(non_camel_case_types)]
437+
#[doc(hidden)]
438+
/// Extension trait for setting the call-flags for the reducer `{reducer_name}`.
439+
///
440+
/// Implemented for [`super::SetReducerFlags`].
441+
///
442+
/// This type is currently unstable and may be removed without a major version bump.
443+
pub trait {set_reducer_flags_trait} {{
444+
/// Set the call-reducer flags for the reducer `{reducer_name}` to `flags`.
445+
///
446+
/// This type is currently unstable and may be removed without a major version bump.
447+
fn {func_name}(&self, flags: __ws::CallReducerFlags);
448+
}}
449+
450+
impl {set_reducer_flags_trait} for super::SetReducerFlags {{
451+
fn {func_name}(&self, flags: __ws::CallReducerFlags) {{
452+
self.imp.set_call_reducer_flags({reducer_name:?}, flags);
453+
}}
454+
}}
434455
"
435456
);
436457

@@ -985,6 +1006,7 @@ impl __sdk::spacetime_module::SpacetimeModule for RemoteModule {{
9851006
type Reducer = Reducer;
9861007
type DbView = RemoteTables;
9871008
type Reducers = RemoteReducers;
1009+
type SetReducerFlags = SetReducerFlags;
9881010
type DbUpdate = DbUpdate;
9891011
type SubscriptionHandle = SubscriptionHandle;
9901012
}}
@@ -999,6 +1021,20 @@ impl __sdk::spacetime_module::InModule for RemoteReducers {{
9991021
type Module = RemoteModule;
10001022
}}
10011023
1024+
#[doc(hidden)]
1025+
/// The `set_reducer_flags` field of [`DbConnection`],
1026+
/// with methods provided by extension traits for each reducer defined by the module.
1027+
/// Each method sets the flags for the reducer with the same name.
1028+
///
1029+
/// This type is currently unstable and may be removed without a major version bump.
1030+
pub struct SetReducerFlags {{
1031+
imp: __sdk::db_connection::DbContextImpl<RemoteModule>,
1032+
}}
1033+
1034+
impl __sdk::spacetime_module::InModule for SetReducerFlags {{
1035+
type Module = RemoteModule;
1036+
}}
1037+
10021038
/// The `db` field of [`EventContext`] and [`DbConnection`],
10031039
/// with methods provided by extension traits for each table defined by the module.
10041040
pub struct RemoteTables {{
@@ -1030,6 +1066,12 @@ pub struct DbConnection {{
10301066
pub db: RemoteTables,
10311067
/// Access to reducers defined by the module via extension traits implemented for [`RemoteReducers`].
10321068
pub reducers: RemoteReducers,
1069+
#[doc(hidden)]
1070+
/// Access to setting the call-flags of each reducer defined for each reducer defined by the module
1071+
/// via extension traits implemented for [`SetReducerFlags`].
1072+
///
1073+
/// This type is currently unstable and may be removed without a major version bump.
1074+
pub set_reducer_flags: SetReducerFlags,
10331075
10341076
imp: __sdk::db_connection::DbContextImpl<RemoteModule>,
10351077
}}
@@ -1041,13 +1083,17 @@ impl __sdk::spacetime_module::InModule for DbConnection {{
10411083
impl __sdk::db_context::DbContext for DbConnection {{
10421084
type DbView = RemoteTables;
10431085
type Reducers = RemoteReducers;
1086+
type SetReducerFlags = SetReducerFlags;
10441087
10451088
fn db(&self) -> &Self::DbView {{
10461089
&self.db
10471090
}}
10481091
fn reducers(&self) -> &Self::Reducers {{
10491092
&self.reducers
10501093
}}
1094+
fn set_reducer_flags(&self) -> &Self::SetReducerFlags {{
1095+
&self.set_reducer_flags
1096+
}}
10511097
10521098
fn is_active(&self) -> bool {{
10531099
self.imp.is_active()
@@ -1147,6 +1193,7 @@ impl __sdk::spacetime_module::DbConnection for DbConnection {{
11471193
Self {{
11481194
db: RemoteTables {{ imp: imp.clone() }},
11491195
reducers: RemoteReducers {{ imp: imp.clone() }},
1196+
set_reducer_flags: SetReducerFlags {{ imp: imp.clone() }},
11501197
imp,
11511198
}}
11521199
}}
@@ -1159,6 +1206,11 @@ pub struct EventContext {{
11591206
pub db: RemoteTables,
11601207
/// Access to reducers defined by the module via extension traits implemented for [`RemoteReducers`].
11611208
pub reducers: RemoteReducers,
1209+
/// Access to setting the call-flags of each reducer defined for each reducer defined by the module
1210+
/// via extension traits implemented for [`SetReducerFlags`].
1211+
///
1212+
/// This type is currently unstable and may be removed without a major version bump.
1213+
pub set_reducer_flags: SetReducerFlags,
11621214
/// The event which caused these callbacks to run.
11631215
pub event: __sdk::event::Event<Reducer>,
11641216
imp: __sdk::db_connection::DbContextImpl<RemoteModule>,
@@ -1171,13 +1223,17 @@ impl __sdk::spacetime_module::InModule for EventContext {{
11711223
impl __sdk::db_context::DbContext for EventContext {{
11721224
type DbView = RemoteTables;
11731225
type Reducers = RemoteReducers;
1226+
type SetReducerFlags = SetReducerFlags;
11741227
11751228
fn db(&self) -> &Self::DbView {{
11761229
&self.db
11771230
}}
11781231
fn reducers(&self) -> &Self::Reducers {{
11791232
&self.reducers
11801233
}}
1234+
fn set_reducer_flags(&self) -> &Self::SetReducerFlags {{
1235+
&self.set_reducer_flags
1236+
}}
11811237
11821238
fn is_active(&self) -> bool {{
11831239
self.imp.is_active()
@@ -1209,6 +1265,7 @@ impl __sdk::spacetime_module::EventContext for EventContext {{
12091265
Self {{
12101266
db: RemoteTables {{ imp: imp.clone() }},
12111267
reducers: RemoteReducers {{ imp: imp.clone() }},
1268+
set_reducer_flags: SetReducerFlags {{ imp: imp.clone() }},
12121269
event,
12131270
imp,
12141271
}}
@@ -1239,11 +1296,13 @@ impl __sdk::spacetime_module::SubscriptionHandle for SubscriptionHandle {{
12391296
pub trait RemoteDbContext: __sdk::DbContext<
12401297
DbView = RemoteTables,
12411298
Reducers = RemoteReducers,
1299+
SetReducerFlags = SetReducerFlags,
12421300
SubscriptionBuilder = __sdk::subscription::SubscriptionBuilder<RemoteModule>,
12431301
> {{}}
12441302
impl<Ctx: __sdk::DbContext<
12451303
DbView = RemoteTables,
12461304
Reducers = RemoteReducers,
1305+
SetReducerFlags = SetReducerFlags,
12471306
SubscriptionBuilder = __sdk::subscription::SubscriptionBuilder<RemoteModule>,
12481307
>> RemoteDbContext for Ctx {{}}
12491308
",

crates/cli/src/subcommands/generate/typescript.rs

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,11 @@ eventContextConstructor: (imp: DBConnectionImpl, event: Event<Reducer>) => {{
388388
dbViewConstructor: (imp: DBConnectionImpl) => {{
389389
return new RemoteTables(imp);
390390
}},
391-
reducersConstructor: (imp: DBConnectionImpl) => {{
392-
return new RemoteReducers(imp);
391+
reducersConstructor: (imp: DBConnectionImpl, setReducerFlags: SetReducerFlags) => {{
392+
return new RemoteReducers(imp, setReducerFlags);
393+
}},
394+
setReducerFlagsConstructor: () => {{
395+
return new SetReducerFlags();
393396
}}"
394397
);
395398
out.dedent(1);
@@ -405,6 +408,10 @@ reducersConstructor: (imp: DBConnectionImpl) => {{
405408

406409
out.newline();
407410

411+
print_set_reducer_flags(module, out);
412+
413+
out.newline();
414+
408415
print_remote_tables(module, out);
409416

410417
out.newline();
@@ -415,7 +422,7 @@ reducersConstructor: (imp: DBConnectionImpl) => {{
415422

416423
writeln!(
417424
out,
418-
"export type EventContext = EventContextInterface<RemoteTables, RemoteReducers, Reducer>;"
425+
"export type EventContext = EventContextInterface<RemoteTables, RemoteReducers, SetReducerFlags, Reducer>;"
419426
);
420427

421428
vec![("index.ts".to_string(), (output.into_inner()))]
@@ -425,7 +432,10 @@ reducersConstructor: (imp: DBConnectionImpl) => {{
425432
fn print_remote_reducers(module: &ModuleDef, out: &mut Indenter) {
426433
writeln!(out, "export class RemoteReducers {{");
427434
out.indent(1);
428-
writeln!(out, "constructor(private connection: DBConnectionImpl) {{}}");
435+
writeln!(
436+
out,
437+
"constructor(private connection: DBConnectionImpl, private setCallReducerFlags: SetReducerFlags) {{}}"
438+
);
429439
out.newline();
430440

431441
for reducer in iter_reducers(module) {
@@ -455,7 +465,7 @@ fn print_remote_reducers(module: &ModuleDef, out: &mut Indenter) {
455465
out.with_indent(|out| {
456466
writeln!(
457467
out,
458-
"this.connection.callReducer(\"{reducer_name}\", new Uint8Array(0));"
468+
"this.connection.callReducer(\"{reducer_name}\", new Uint8Array(0), this.setCallReducerFlags.{reducer_function_name}Flags);"
459469
);
460470
});
461471
} else {
@@ -468,7 +478,7 @@ fn print_remote_reducers(module: &ModuleDef, out: &mut Indenter) {
468478
"{reducer_variant}.getTypeScriptAlgebraicType().serialize(__writer, __args);"
469479
);
470480
writeln!(out, "let __argsBuffer = __writer.getBuffer();");
471-
writeln!(out, "this.connection.callReducer(\"{reducer_name}\", __argsBuffer);");
481+
writeln!(out, "this.connection.callReducer(\"{reducer_name}\", __argsBuffer, this.setCallReducerFlags.{reducer_function_name}Flags);");
472482
});
473483
}
474484
writeln!(out, "}}");
@@ -503,6 +513,25 @@ fn print_remote_reducers(module: &ModuleDef, out: &mut Indenter) {
503513
writeln!(out, "}}");
504514
}
505515

516+
fn print_set_reducer_flags(module: &ModuleDef, out: &mut Indenter) {
517+
writeln!(out, "export class SetReducerFlags {{");
518+
out.indent(1);
519+
520+
for reducer in iter_reducers(module) {
521+
let reducer_function_name = reducer_function_name(reducer);
522+
writeln!(out, "{reducer_function_name}Flags: CallReducerFlags = 'FullUpdate';");
523+
writeln!(out, "{reducer_function_name}(flags: CallReducerFlags) {{");
524+
out.with_indent(|out| {
525+
writeln!(out, "this.{reducer_function_name}Flags = flags;");
526+
});
527+
writeln!(out, "}}");
528+
out.newline();
529+
}
530+
531+
out.dedent(1);
532+
writeln!(out, "}}");
533+
}
534+
506535
fn print_remote_tables(module: &ModuleDef, out: &mut Indenter) {
507536
writeln!(out, "export class RemoteTables {{");
508537
out.indent(1);
@@ -533,7 +562,7 @@ fn print_remote_tables(module: &ModuleDef, out: &mut Indenter) {
533562
fn print_db_connection(_module: &ModuleDef, out: &mut Indenter) {
534563
writeln!(
535564
out,
536-
"export class DBConnection extends DBConnectionImpl<RemoteTables, RemoteReducers> {{"
565+
"export class DBConnection extends DBConnectionImpl<RemoteTables, RemoteReducers, SetReducerFlags> {{"
537566
);
538567
out.indent(1);
539568
writeln!(out, "static builder = (): DBConnectionBuilder<DBConnection> => {{");
@@ -575,6 +604,7 @@ fn print_spacetimedb_imports(out: &mut Indenter) {
575604
"DBConnectionBuilder",
576605
"TableCache",
577606
"BinaryWriter",
607+
"CallReducerFlags",
578608
"EventContextInterface",
579609
"BinaryReader",
580610
"DBConnectionImpl",

crates/cli/src/subcommands/subscribe.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ where
196196
S: TryStream<Ok = WsMessage> + Unpin,
197197
S::Error: std::error::Error + Send + Sync + 'static,
198198
{
199+
const RECV_TX_UPDATE: &str = "protocol error: received transaction update before initial subscription update";
200+
199201
while let Some(msg) = ws.try_next().await? {
200202
let Some(msg) = parse_msg_json(&msg) else { continue };
201203
match msg {
@@ -207,12 +209,12 @@ where
207209
}
208210
break;
209211
}
210-
ws::ServerMessage::TransactionUpdate(ws::TransactionUpdate { status, .. }) => {
211-
let message = match status {
212-
ws::UpdateStatus::Failed(msg) => msg,
213-
_ => "protocol error: received transaction update before initial subscription update".into(),
214-
};
215-
anyhow::bail!(message)
212+
ws::ServerMessage::TransactionUpdate(ws::TransactionUpdate { status, .. }) => anyhow::bail!(match status {
213+
ws::UpdateStatus::Failed(msg) => msg,
214+
_ => RECV_TX_UPDATE.into(),
215+
}),
216+
ws::ServerMessage::TransactionUpdateLight(ws::TransactionUpdateLight { .. }) => {
217+
anyhow::bail!(RECV_TX_UPDATE)
216218
}
217219
_ => continue,
218220
}
@@ -248,7 +250,8 @@ where
248250
ws::ServerMessage::InitialSubscription(_) => {
249251
anyhow::bail!("protocol error: received a second initial subscription update")
250252
}
251-
ws::ServerMessage::TransactionUpdate(ws::TransactionUpdate {
253+
ws::ServerMessage::TransactionUpdateLight(ws::TransactionUpdateLight { update, .. })
254+
| ws::ServerMessage::TransactionUpdate(ws::TransactionUpdate {
252255
status: ws::UpdateStatus::Committed(update),
253256
..
254257
}) => {

0 commit comments

Comments
 (0)