Migrate C# client-side reducer enum to the new syntax (#2033)

This commit is contained in:
Ingvar Stepanyan
2024-12-04 16:41:16 +00:00
committed by GitHub
parent a5feed08b0
commit 3902f7562e
8 changed files with 317 additions and 371 deletions
+9 -32
View File
@@ -120,6 +120,7 @@ jobs:
run: |
sudo mkdir /stdb
sudo chmod 777 /stdb
- name: Checkout C# SDK
uses: actions/checkout@v4
with:
@@ -127,42 +128,18 @@ jobs:
ref: staging
path: spacetimedb-csharp-sdk
- name: C# SDK tests
- name: Setup NuGet override for C# SDK
working-directory: spacetimedb-csharp-sdk
run: |
( cd crates/bindings-csharp/BSATN.Runtime && dotnet pack )
cd spacetimedb-csharp-sdk
# Write out the nuget config file to `nuget.config`. This causes the spacetimedb-csharp-sdk repository
# to be aware of the local versions of the `bindings-csharp` packages in SpacetimeDB, and use them if
# available. Otherwise, `spacetimedb-csharp-sdk` will use the NuGet versions of the packages.
# This means that (if version numbers match) we will test the local versions of the C# packages, even
# if they're not pushed to NuGet.
# See https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file for more info on the config file,
# and https://tldp.org/LDP/abs/html/here-docs.html for more info on this bash feature.
cat >nuget.config <<EOF
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!-- Local NuGet repositories -->
<add key="Local SpacetimeDB.BSATN.Runtime" value="../crates/bindings-csharp/BSATN.Runtime/bin/Release" />
</packageSources>
<packageSourceMapping>
<!-- Ensure that SpacetimeDB.BSATN.Runtime is used from the local folder. -->
<!-- Otherwise we risk an outdated version being quietly pulled from NuGet for testing. -->
<packageSource key="Local SpacetimeDB.BSATN.Runtime">
<package pattern="SpacetimeDB.BSATN.Runtime" />
</packageSource>
<!-- Fallback to NuGet for other packages. -->
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
</packageSourceMapping>
</configuration>
EOF
dotnet pack ../crates/bindings-csharp/BSATN.Runtime
./tools~/write-nuget-config.sh ..
# clear package caches, so we get fresh ones even if version numbers haven't changed
dotnet nuget locals all --clear
dotnet test
- name: Run C# SDK tests
working-directory: spacetimedb-csharp-sdk
run: dotnet test
lints:
name: Lints
@@ -18,9 +18,7 @@ namespace SpacetimeDB.Internal
[DataMember(Name = "sql")]
public string Sql;
public RawRowLevelSecurityDefV9(
string Sql
)
public RawRowLevelSecurityDefV9(string Sql)
{
this.Sql = Sql;
}
@@ -18,9 +18,7 @@ namespace SpacetimeDB.Internal
[DataMember(Name = "columns")]
public System.Collections.Generic.List<ushort> Columns;
public RawUniqueConstraintDataV9(
System.Collections.Generic.List<ushort> Columns
)
public RawUniqueConstraintDataV9(System.Collections.Generic.List<ushort> Columns)
{
this.Columns = Columns;
}
@@ -18,9 +18,7 @@ namespace SpacetimeDB.Internal
[DataMember(Name = "types")]
public System.Collections.Generic.List<SpacetimeDB.BSATN.AlgebraicType> Types;
public Typespace(
System.Collections.Generic.List<SpacetimeDB.BSATN.AlgebraicType> Types
)
public Typespace(System.Collections.Generic.List<SpacetimeDB.BSATN.AlgebraicType> Types)
{
this.Types = Types;
}
+100 -97
View File
@@ -6,7 +6,7 @@ use std::ops::Deref;
use convert_case::{Case, Casing};
use spacetimedb_lib::sats::{AlgebraicType, AlgebraicTypeRef, ArrayType, ProductType, SumType};
use spacetimedb_lib::ReducerDef;
use spacetimedb_lib::{ProductTypeElement, ReducerDef};
use spacetimedb_primitives::ColList;
use spacetimedb_schema::def::{BTreeAlgorithm, IndexAlgorithm};
use spacetimedb_schema::schema::TableSchema;
@@ -265,26 +265,25 @@ pub fn autogen_csharp_sum(ctx: &GenCtx, name: &str, sum_type: &SumType, namespac
}
pub fn autogen_csharp_tuple(ctx: &GenCtx, name: &str, tuple: &ProductType, namespace: &str) -> String {
autogen_csharp_product_table_common(ctx, name, tuple, None, namespace)
autogen_csharp_product_common_file(ctx, name, &tuple.elements, "", namespace)
}
#[allow(deprecated)]
pub fn autogen_csharp_table(ctx: &GenCtx, table: &TableDescHack, namespace: &str) -> String {
let tuple = ctx.typespace[table.data].as_product().unwrap();
autogen_csharp_product_table_common(
autogen_csharp_product_common_file(
ctx,
csharp_typename(ctx, table.data),
tuple,
Some(table.schema.clone()),
&ctx.typespace[table.data].as_product().unwrap().elements,
"IDatabaseRow",
namespace,
)
}
fn autogen_csharp_product_table_common(
fn autogen_csharp_product_common_file(
ctx: &GenCtx,
name: &str,
product_type: &ProductType,
schema: Option<TableSchema>,
product_type_elems: &[ProductTypeElement],
base: &str,
namespace: &str,
) -> String {
let mut output = CsharpAutogen::new(
@@ -292,16 +291,29 @@ fn autogen_csharp_product_table_common(
&["System.Collections.Generic", "System.Runtime.Serialization"],
);
autogen_csharp_product_common(ctx, &mut output, name, product_type_elems, base, namespace, |_| {});
output.into_inner()
}
fn autogen_csharp_product_common(
ctx: &GenCtx,
output: &mut CodeIndenter<String>,
name: &str,
product_type_elems: &[ProductTypeElement],
base: &str,
namespace: &str,
extra_body: impl FnOnce(&mut CodeIndenter<String>),
) {
writeln!(output, "[SpacetimeDB.Type]");
writeln!(output, "[DataContract]");
write!(output, "public partial class {name}");
if schema.is_some() {
write!(output, " : IDatabaseRow");
if !base.is_empty() {
write!(output, " : {base}");
}
writeln!(output);
indented_block(&mut output, |output| {
let fields = product_type
.elements
indented_block(output, |output| {
let fields = product_type_elems
.iter()
.map(|field| {
let orig_name = field
@@ -321,32 +333,38 @@ fn autogen_csharp_product_table_common(
})
.collect::<Vec<_>>();
// Generate fully-parameterized constructor.
writeln!(output);
writeln!(output, "public {name}(");
{
indent_scope!(output);
for (i, (field_name, ty)) in fields.iter().enumerate() {
if i != 0 {
writeln!(output, ",");
}
write!(output, "{ty} {field_name}");
}
}
writeln!(output);
writeln!(output, ")");
indented_block(output, |output| {
for (field_name, _ty) in fields.iter() {
writeln!(output, "this.{field_name} = {field_name};");
}
});
writeln!(output);
// Generate default constructor (if the one above is not already parameterless).
// If we don't have any fields, the default constructor is fine, otherwise we need to generate our own.
if !fields.is_empty() {
// Generate fully-parameterized constructor.
writeln!(output);
write!(output, "public {name}(");
if fields.len() > 1 {
writeln!(output);
}
{
indent_scope!(output);
for (i, (field_name, ty)) in fields.iter().enumerate() {
if i != 0 {
writeln!(output, ",");
}
write!(output, "{ty} {field_name}");
}
}
if fields.len() > 1 {
writeln!(output);
}
writeln!(output, ")");
indented_block(output, |output| {
for (field_name, _ty) in fields.iter() {
writeln!(output, "this.{field_name} = {field_name};");
}
});
writeln!(output);
// Generate default constructor.
writeln!(output, "public {name}()");
indented_block(output, |output| {
for ((field_name, _ty), field) in fields.iter().zip(&*product_type.elements) {
for ((field_name, _ty), field) in fields.iter().zip(product_type_elems) {
if let Some(default) = default_init(ctx, &field.algebraic_type) {
writeln!(output, "this.{field_name} = {default};");
}
@@ -354,9 +372,9 @@ fn autogen_csharp_product_table_common(
});
writeln!(output);
}
});
output.into_inner()
extra_body(output);
});
}
fn indented_block<R>(output: &mut CodeIndenter<String>, f: impl FnOnce(&mut CodeIndenter<String>) -> R) -> R {
@@ -517,40 +535,6 @@ fn autogen_csharp_access_funcs_for_struct(
}
}
pub fn autogen_csharp_reducer(ctx: &GenCtx, reducer: &ReducerDef, namespace: &str) -> String {
let func_name = &*reducer.name;
let func_name_pascal_case = func_name.to_case(Case::Pascal);
let mut output = CsharpAutogen::new(namespace, &[]);
//Args struct
writeln!(output, "[SpacetimeDB.Type]");
writeln!(output, "public partial class {func_name_pascal_case} : IReducerArgs");
indented_block(&mut output, |output| {
writeln!(output, "string IReducerArgs.ReducerName => \"{func_name}\";");
if !reducer.args.is_empty() {
writeln!(output);
}
for arg in reducer.args.iter() {
let name = arg
.name
.as_deref()
.unwrap_or_else(|| panic!("reducer args should have names: {func_name}"));
let arg_type_str = ty_fmt(ctx, &arg.algebraic_type, namespace);
let field_name = name.to_case(Case::Pascal);
write!(output, "public {arg_type_str} {field_name}");
// Skip default initializer if it's the same as the implicit default.
if let Some(default) = default_init(ctx, &arg.algebraic_type) {
write!(output, " = {default}");
}
writeln!(output, ";");
}
});
output.into_inner()
}
pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str) -> Vec<(String, String)> {
let mut results = Vec::new();
@@ -577,7 +561,14 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
.map(|reducer| reducer.name.deref().to_case(Case::Pascal))
.collect();
let mut output = CsharpAutogen::new(namespace, &["SpacetimeDB.ClientApi", "System.Collections.Generic"]);
let mut output = CsharpAutogen::new(
namespace,
&[
"SpacetimeDB.ClientApi",
"System.Collections.Generic",
"System.Runtime.Serialization",
],
);
writeln!(output, "public sealed class RemoteTables");
indented_block(&mut output, |output| {
@@ -665,12 +656,12 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
let delegate_separator = if !reducer.args.is_empty() { ", " } else { "" };
let mut func_params: String = String::new();
let mut field_inits: String = String::new();
let mut func_args: String = String::new();
for (arg_i, arg) in reducer.args.iter().enumerate() {
if arg_i != 0 {
func_params.push_str(", ");
field_inits.push_str(", ");
func_args.push_str(", ");
}
let name = arg
@@ -679,10 +670,9 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
.unwrap_or_else(|| panic!("reducer args should have names: {func_name}"));
let arg_type_str = ty_fmt(ctx, &arg.algebraic_type, namespace);
let arg_name = name.to_case(Case::Camel);
let field_name = name.to_case(Case::Pascal);
write!(func_params, "{arg_type_str} {arg_name}").unwrap();
write!(field_inits, "{field_name} = {arg_name}").unwrap();
write!(func_args, "{arg_name}").unwrap();
}
writeln!(
@@ -699,14 +689,14 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
indented_block(output, |output| {
writeln!(
output,
"conn.InternalCallReducer(new {func_name_pascal_case} {{ {field_inits} }}, this.SetCallReducerFlags.{func_name_pascal_case}Flags);"
"conn.InternalCallReducer(new Reducer.{func_name_pascal_case}({func_args}), this.SetCallReducerFlags.{func_name_pascal_case}Flags);"
);
});
writeln!(output);
writeln!(
output,
"public bool Invoke{func_name_pascal_case}(EventContext ctx, {func_name_pascal_case} args)"
"public bool Invoke{func_name_pascal_case}(EventContext ctx, Reducer.{func_name_pascal_case} args)"
);
indented_block(output, |output| {
writeln!(output, "if (On{func_name_pascal_case} == null) return false;");
@@ -765,18 +755,31 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
});
writeln!(output);
writeln!(output, "[Type]");
writeln!(output, "public partial record Reducer : TaggedEnum<(");
{
indent_scope!(output);
for reducer_name in &reducer_names {
writeln!(output, "{reducer_name} {reducer_name},");
writeln!(output, "public abstract partial class Reducer");
indented_block(&mut output, |output| {
// Prevent instantiation of this class from outside.
writeln!(output, "private Reducer() {{ }}");
writeln!(output);
for (reducer, reducer_name) in std::iter::zip(&reducers, &reducer_names) {
let reducer_str_name = &reducer.name;
autogen_csharp_product_common(
ctx,
output,
reducer_name,
&reducer.args,
"Reducer, IReducerArgs",
namespace,
|output| {
writeln!(output, "string IReducerArgs.ReducerName => \"{reducer_str_name}\";");
},
);
writeln!(output);
}
writeln!(output, "Unit StdbNone,");
writeln!(output, "Unit StdbIdentityConnected,");
writeln!(output, "Unit StdbIdentityDisconnected");
}
writeln!(output, ")>;");
writeln!(output, "public class StdbNone : Reducer {{}}");
writeln!(output, "public class StdbIdentityConnected : Reducer {{}}");
writeln!(output, "public class StdbIdentityDisconnected : Reducer {{}}");
});
writeln!(output);
writeln!(
output,
@@ -818,19 +821,19 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
let reducer_str_name = &reducer.name;
writeln!(
output,
"\"{reducer_str_name}\" => new Reducer.{reducer_name}(BSATNHelpers.Decode<{reducer_name}>(encodedArgs)),"
"\"{reducer_str_name}\" => BSATNHelpers.Decode<Reducer.{reducer_name}>(encodedArgs),"
);
}
writeln!(output, "\"<none>\" => new Reducer.StdbNone(default),");
writeln!(output, "\"<none>\" => new Reducer.StdbNone(),");
writeln!(
output,
"\"__identity_connected__\" => new Reducer.StdbIdentityConnected(default),"
"\"__identity_connected__\" => new Reducer.StdbIdentityConnected(),"
);
writeln!(
output,
"\"__identity_disconnected__\" => new Reducer.StdbIdentityDisconnected(default),"
"\"__identity_disconnected__\" => new Reducer.StdbIdentityDisconnected(),"
);
writeln!(output, "\"\" => new Reducer.StdbNone(default),"); //Transaction from CLI command
writeln!(output, "\"\" => new Reducer.StdbNone(),"); //Transaction from CLI command
writeln!(
output,
r#"var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {{reducer}}")"#
@@ -859,7 +862,7 @@ pub fn autogen_csharp_globals(ctx: &GenCtx, items: &[GenItem], namespace: &str)
for reducer_name in &reducer_names {
writeln!(
output,
"Reducer.{reducer_name}(var args) => Reducers.Invoke{reducer_name}(eventContext, args),"
"Reducer.{reducer_name} args => Reducers.Invoke{reducer_name}(eventContext, args),"
);
}
writeln!(output, "Reducer.StdbNone or");
+1 -6
View File
@@ -20,7 +20,6 @@ use spacetimedb_schema::def::{ModuleDef, ReducerDef, ScopedTypeName, TableDef, T
use spacetimedb_schema::identifier::Identifier;
use spacetimedb_schema::schema::{Schema, TableSchema};
use std::fs;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use wasmtime::{Caller, StoreContextMut};
@@ -367,11 +366,7 @@ impl GenItem {
}
_ => todo!(),
},
GenItem::Reducer(reducer) => {
let code = csharp::autogen_csharp_reducer(ctx, reducer, namespace);
let pascalcase = reducer.name.deref().to_case(Case::Pascal);
Some((pascalcase + "Reducer.cs", code))
}
GenItem::Reducer(_) => None,
}
}
}
@@ -1,47 +1,8 @@
---
source: crates/cli/tests/codegen.rs
expression: outfiles
snapshot_kind: text
---
"AddPlayerReducer.cs" = '''
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.
// <auto-generated />
#nullable enable
using System;
namespace SpacetimeDB
{
[SpacetimeDB.Type]
public partial class AddPlayer : IReducerArgs
{
string IReducerArgs.ReducerName => "add_player";
public string Name = "";
}
}
'''
"AddPrivateReducer.cs" = '''
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.
// <auto-generated />
#nullable enable
using System;
namespace SpacetimeDB
{
[SpacetimeDB.Type]
public partial class AddPrivate : IReducerArgs
{
string IReducerArgs.ReducerName => "add_private";
public string Name = "";
}
}
'''
"Baz.cs" = '''
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.
@@ -62,9 +23,7 @@ namespace SpacetimeDB
[DataMember(Name = "field")]
public string Field;
public Baz(
string Field
)
public Baz(string Field)
{
this.Field = Field;
}
@@ -77,46 +36,6 @@ namespace SpacetimeDB
}
}
'''
"DeletePlayerReducer.cs" = '''
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.
// <auto-generated />
#nullable enable
using System;
namespace SpacetimeDB
{
[SpacetimeDB.Type]
public partial class DeletePlayer : IReducerArgs
{
string IReducerArgs.ReducerName => "delete_player";
public ulong Id;
}
}
'''
"DeletePlayersByNameReducer.cs" = '''
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.
// <auto-generated />
#nullable enable
using System;
namespace SpacetimeDB
{
[SpacetimeDB.Type]
public partial class DeletePlayersByName : IReducerArgs
{
string IReducerArgs.ReducerName => "delete_players_by_name";
public string Name = "";
}
}
'''
"Foobar.cs" = '''
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.
@@ -322,9 +241,7 @@ namespace SpacetimeDB
[DataMember(Name = "name")]
public string Name;
public Private(
string Name
)
public Private(string Name)
{
this.Name = Name;
}
@@ -337,24 +254,6 @@ namespace SpacetimeDB
}
}
'''
"QueryPrivateReducer.cs" = '''
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.
// <auto-generated />
#nullable enable
using System;
namespace SpacetimeDB
{
[SpacetimeDB.Type]
public partial class QueryPrivate : IReducerArgs
{
string IReducerArgs.ReducerName => "query_private";
}
}
'''
"RepeatingTestArg.cs" = '''
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.
@@ -398,26 +297,6 @@ namespace SpacetimeDB
}
}
'''
"RepeatingTestReducer.cs" = '''
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.
// <auto-generated />
#nullable enable
using System;
namespace SpacetimeDB
{
[SpacetimeDB.Type]
public partial class RepeatingTest : IReducerArgs
{
string IReducerArgs.ReducerName => "repeating_test";
public SpacetimeDB.RepeatingTestArg Arg = new();
}
}
'''
"TestA.cs" = '''
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.
@@ -481,9 +360,7 @@ namespace SpacetimeDB
[DataMember(Name = "foo")]
public string Foo;
public TestB(
string Foo
)
public TestB(string Foo)
{
this.Foo = Foo;
}
@@ -496,24 +373,6 @@ namespace SpacetimeDB
}
}
'''
"TestBtreeIndexArgsReducer.cs" = '''
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.
// <auto-generated />
#nullable enable
using System;
namespace SpacetimeDB
{
[SpacetimeDB.Type]
public partial class TestBtreeIndexArgs : IReducerArgs
{
string IReducerArgs.ReducerName => "test_btree_index_args";
}
}
'''
"TestD.cs" = '''
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.
@@ -534,9 +393,7 @@ namespace SpacetimeDB
[DataMember(Name = "test_c")]
public SpacetimeDB.Namespace.Types.TestC? TestC;
public TestD(
SpacetimeDB.Namespace.Types.TestC? TestC
)
public TestD(SpacetimeDB.Namespace.Types.TestC? TestC)
{
this.TestC = TestC;
}
@@ -607,9 +464,7 @@ namespace SpacetimeDB
[DataMember(Name = "field")]
public SpacetimeDB.Foobar Field;
public TestFoobar(
SpacetimeDB.Foobar Field
)
public TestFoobar(SpacetimeDB.Foobar Field)
{
this.Field = Field;
}
@@ -622,29 +477,6 @@ namespace SpacetimeDB
}
}
'''
"TestReducer.cs" = '''
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.
// <auto-generated />
#nullable enable
using System;
namespace SpacetimeDB
{
[SpacetimeDB.Type]
public partial class Test : IReducerArgs
{
string IReducerArgs.ReducerName => "test";
public SpacetimeDB.TestA Arg = new();
public SpacetimeDB.TestB Arg2 = new();
public SpacetimeDB.Namespace.Types.TestC Arg3;
public SpacetimeDB.Namespace.TestF Arg4 = null!;
}
}
'''
"_Globals/SpacetimeDBClient.cs" = '''
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD.
@@ -655,6 +487,7 @@ namespace SpacetimeDB
using System;
using SpacetimeDB.ClientApi;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace SpacetimeDB
{
@@ -887,10 +720,10 @@ namespace SpacetimeDB
public void AddPlayer(string name)
{
conn.InternalCallReducer(new AddPlayer { Name = name }, this.SetCallReducerFlags.AddPlayerFlags);
conn.InternalCallReducer(new Reducer.AddPlayer(name), this.SetCallReducerFlags.AddPlayerFlags);
}
public bool InvokeAddPlayer(EventContext ctx, AddPlayer args)
public bool InvokeAddPlayer(EventContext ctx, Reducer.AddPlayer args)
{
if (OnAddPlayer == null) return false;
OnAddPlayer(
@@ -904,10 +737,10 @@ namespace SpacetimeDB
public void AddPrivate(string name)
{
conn.InternalCallReducer(new AddPrivate { Name = name }, this.SetCallReducerFlags.AddPrivateFlags);
conn.InternalCallReducer(new Reducer.AddPrivate(name), this.SetCallReducerFlags.AddPrivateFlags);
}
public bool InvokeAddPrivate(EventContext ctx, AddPrivate args)
public bool InvokeAddPrivate(EventContext ctx, Reducer.AddPrivate args)
{
if (OnAddPrivate == null) return false;
OnAddPrivate(
@@ -921,10 +754,10 @@ namespace SpacetimeDB
public void DeletePlayer(ulong id)
{
conn.InternalCallReducer(new DeletePlayer { Id = id }, this.SetCallReducerFlags.DeletePlayerFlags);
conn.InternalCallReducer(new Reducer.DeletePlayer(id), this.SetCallReducerFlags.DeletePlayerFlags);
}
public bool InvokeDeletePlayer(EventContext ctx, DeletePlayer args)
public bool InvokeDeletePlayer(EventContext ctx, Reducer.DeletePlayer args)
{
if (OnDeletePlayer == null) return false;
OnDeletePlayer(
@@ -938,10 +771,10 @@ namespace SpacetimeDB
public void DeletePlayersByName(string name)
{
conn.InternalCallReducer(new DeletePlayersByName { Name = name }, this.SetCallReducerFlags.DeletePlayersByNameFlags);
conn.InternalCallReducer(new Reducer.DeletePlayersByName(name), this.SetCallReducerFlags.DeletePlayersByNameFlags);
}
public bool InvokeDeletePlayersByName(EventContext ctx, DeletePlayersByName args)
public bool InvokeDeletePlayersByName(EventContext ctx, Reducer.DeletePlayersByName args)
{
if (OnDeletePlayersByName == null) return false;
OnDeletePlayersByName(
@@ -955,10 +788,10 @@ namespace SpacetimeDB
public void QueryPrivate()
{
conn.InternalCallReducer(new QueryPrivate { }, this.SetCallReducerFlags.QueryPrivateFlags);
conn.InternalCallReducer(new Reducer.QueryPrivate(), this.SetCallReducerFlags.QueryPrivateFlags);
}
public bool InvokeQueryPrivate(EventContext ctx, QueryPrivate args)
public bool InvokeQueryPrivate(EventContext ctx, Reducer.QueryPrivate args)
{
if (OnQueryPrivate == null) return false;
OnQueryPrivate(
@@ -971,10 +804,10 @@ namespace SpacetimeDB
public void RepeatingTest(SpacetimeDB.RepeatingTestArg arg)
{
conn.InternalCallReducer(new RepeatingTest { Arg = arg }, this.SetCallReducerFlags.RepeatingTestFlags);
conn.InternalCallReducer(new Reducer.RepeatingTest(arg), this.SetCallReducerFlags.RepeatingTestFlags);
}
public bool InvokeRepeatingTest(EventContext ctx, RepeatingTest args)
public bool InvokeRepeatingTest(EventContext ctx, Reducer.RepeatingTest args)
{
if (OnRepeatingTest == null) return false;
OnRepeatingTest(
@@ -988,10 +821,10 @@ namespace SpacetimeDB
public void Test(SpacetimeDB.TestA arg, SpacetimeDB.TestB arg2, SpacetimeDB.Namespace.Types.TestC arg3, SpacetimeDB.Namespace.TestF arg4)
{
conn.InternalCallReducer(new Test { Arg = arg, Arg2 = arg2, Arg3 = arg3, Arg4 = arg4 }, this.SetCallReducerFlags.TestFlags);
conn.InternalCallReducer(new Reducer.Test(arg, arg2, arg3, arg4), this.SetCallReducerFlags.TestFlags);
}
public bool InvokeTest(EventContext ctx, Test args)
public bool InvokeTest(EventContext ctx, Reducer.Test args)
{
if (OnTest == null) return false;
OnTest(
@@ -1008,10 +841,10 @@ namespace SpacetimeDB
public void TestBtreeIndexArgs()
{
conn.InternalCallReducer(new TestBtreeIndexArgs { }, this.SetCallReducerFlags.TestBtreeIndexArgsFlags);
conn.InternalCallReducer(new Reducer.TestBtreeIndexArgs(), this.SetCallReducerFlags.TestBtreeIndexArgsFlags);
}
public bool InvokeTestBtreeIndexArgs(EventContext ctx, TestBtreeIndexArgs args)
public bool InvokeTestBtreeIndexArgs(EventContext ctx, Reducer.TestBtreeIndexArgs args)
{
if (OnTestBtreeIndexArgs == null) return false;
OnTestBtreeIndexArgs(
@@ -1056,20 +889,164 @@ namespace SpacetimeDB
}
}
[Type]
public partial record Reducer : TaggedEnum<(
AddPlayer AddPlayer,
AddPrivate AddPrivate,
DeletePlayer DeletePlayer,
DeletePlayersByName DeletePlayersByName,
QueryPrivate QueryPrivate,
RepeatingTest RepeatingTest,
Test Test,
TestBtreeIndexArgs TestBtreeIndexArgs,
Unit StdbNone,
Unit StdbIdentityConnected,
Unit StdbIdentityDisconnected
)>;
public abstract partial class Reducer
{
private Reducer() { }
[SpacetimeDB.Type]
[DataContract]
public partial class AddPlayer : Reducer, IReducerArgs
{
[DataMember(Name = "name")]
public string Name;
public AddPlayer(string Name)
{
this.Name = Name;
}
public AddPlayer()
{
this.Name = "";
}
string IReducerArgs.ReducerName => "add_player";
}
[SpacetimeDB.Type]
[DataContract]
public partial class AddPrivate : Reducer, IReducerArgs
{
[DataMember(Name = "name")]
public string Name;
public AddPrivate(string Name)
{
this.Name = Name;
}
public AddPrivate()
{
this.Name = "";
}
string IReducerArgs.ReducerName => "add_private";
}
[SpacetimeDB.Type]
[DataContract]
public partial class DeletePlayer : Reducer, IReducerArgs
{
[DataMember(Name = "id")]
public ulong Id;
public DeletePlayer(ulong Id)
{
this.Id = Id;
}
public DeletePlayer()
{
}
string IReducerArgs.ReducerName => "delete_player";
}
[SpacetimeDB.Type]
[DataContract]
public partial class DeletePlayersByName : Reducer, IReducerArgs
{
[DataMember(Name = "name")]
public string Name;
public DeletePlayersByName(string Name)
{
this.Name = Name;
}
public DeletePlayersByName()
{
this.Name = "";
}
string IReducerArgs.ReducerName => "delete_players_by_name";
}
[SpacetimeDB.Type]
[DataContract]
public partial class QueryPrivate : Reducer, IReducerArgs
{
string IReducerArgs.ReducerName => "query_private";
}
[SpacetimeDB.Type]
[DataContract]
public partial class RepeatingTest : Reducer, IReducerArgs
{
[DataMember(Name = "arg")]
public SpacetimeDB.RepeatingTestArg Arg;
public RepeatingTest(SpacetimeDB.RepeatingTestArg Arg)
{
this.Arg = Arg;
}
public RepeatingTest()
{
this.Arg = new();
}
string IReducerArgs.ReducerName => "repeating_test";
}
[SpacetimeDB.Type]
[DataContract]
public partial class Test : Reducer, IReducerArgs
{
[DataMember(Name = "arg")]
public SpacetimeDB.TestA Arg;
[DataMember(Name = "arg2")]
public SpacetimeDB.TestB Arg2;
[DataMember(Name = "arg3")]
public SpacetimeDB.Namespace.Types.TestC Arg3;
[DataMember(Name = "arg4")]
public SpacetimeDB.Namespace.TestF Arg4;
public Test(
SpacetimeDB.TestA Arg,
SpacetimeDB.TestB Arg2,
SpacetimeDB.Namespace.Types.TestC Arg3,
SpacetimeDB.Namespace.TestF Arg4
)
{
this.Arg = Arg;
this.Arg2 = Arg2;
this.Arg3 = Arg3;
this.Arg4 = Arg4;
}
public Test()
{
this.Arg = new();
this.Arg2 = new();
this.Arg4 = null!;
}
string IReducerArgs.ReducerName => "test";
}
[SpacetimeDB.Type]
[DataContract]
public partial class TestBtreeIndexArgs : Reducer, IReducerArgs
{
string IReducerArgs.ReducerName => "test_btree_index_args";
}
public class StdbNone : Reducer {}
public class StdbIdentityConnected : Reducer {}
public class StdbIdentityDisconnected : Reducer {}
}
public class DbConnection : DbConnectionBase<DbConnection, Reducer>
{
public readonly RemoteTables Db = new();
@@ -1096,18 +1073,18 @@ namespace SpacetimeDB
{
var encodedArgs = update.ReducerCall.Args;
return update.ReducerCall.ReducerName switch {
"add_player" => new Reducer.AddPlayer(BSATNHelpers.Decode<AddPlayer>(encodedArgs)),
"add_private" => new Reducer.AddPrivate(BSATNHelpers.Decode<AddPrivate>(encodedArgs)),
"delete_player" => new Reducer.DeletePlayer(BSATNHelpers.Decode<DeletePlayer>(encodedArgs)),
"delete_players_by_name" => new Reducer.DeletePlayersByName(BSATNHelpers.Decode<DeletePlayersByName>(encodedArgs)),
"query_private" => new Reducer.QueryPrivate(BSATNHelpers.Decode<QueryPrivate>(encodedArgs)),
"repeating_test" => new Reducer.RepeatingTest(BSATNHelpers.Decode<RepeatingTest>(encodedArgs)),
"test" => new Reducer.Test(BSATNHelpers.Decode<Test>(encodedArgs)),
"test_btree_index_args" => new Reducer.TestBtreeIndexArgs(BSATNHelpers.Decode<TestBtreeIndexArgs>(encodedArgs)),
"<none>" => new Reducer.StdbNone(default),
"__identity_connected__" => new Reducer.StdbIdentityConnected(default),
"__identity_disconnected__" => new Reducer.StdbIdentityDisconnected(default),
"" => new Reducer.StdbNone(default),
"add_player" => BSATNHelpers.Decode<Reducer.AddPlayer>(encodedArgs),
"add_private" => BSATNHelpers.Decode<Reducer.AddPrivate>(encodedArgs),
"delete_player" => BSATNHelpers.Decode<Reducer.DeletePlayer>(encodedArgs),
"delete_players_by_name" => BSATNHelpers.Decode<Reducer.DeletePlayersByName>(encodedArgs),
"query_private" => BSATNHelpers.Decode<Reducer.QueryPrivate>(encodedArgs),
"repeating_test" => BSATNHelpers.Decode<Reducer.RepeatingTest>(encodedArgs),
"test" => BSATNHelpers.Decode<Reducer.Test>(encodedArgs),
"test_btree_index_args" => BSATNHelpers.Decode<Reducer.TestBtreeIndexArgs>(encodedArgs),
"<none>" => new Reducer.StdbNone(),
"__identity_connected__" => new Reducer.StdbIdentityConnected(),
"__identity_disconnected__" => new Reducer.StdbIdentityDisconnected(),
"" => new Reducer.StdbNone(),
var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}")
};
}
@@ -1119,14 +1096,14 @@ namespace SpacetimeDB
{
var eventContext = (EventContext)context;
return reducer switch {
Reducer.AddPlayer(var args) => Reducers.InvokeAddPlayer(eventContext, args),
Reducer.AddPrivate(var args) => Reducers.InvokeAddPrivate(eventContext, args),
Reducer.DeletePlayer(var args) => Reducers.InvokeDeletePlayer(eventContext, args),
Reducer.DeletePlayersByName(var args) => Reducers.InvokeDeletePlayersByName(eventContext, args),
Reducer.QueryPrivate(var args) => Reducers.InvokeQueryPrivate(eventContext, args),
Reducer.RepeatingTest(var args) => Reducers.InvokeRepeatingTest(eventContext, args),
Reducer.Test(var args) => Reducers.InvokeTest(eventContext, args),
Reducer.TestBtreeIndexArgs(var args) => Reducers.InvokeTestBtreeIndexArgs(eventContext, args),
Reducer.AddPlayer args => Reducers.InvokeAddPlayer(eventContext, args),
Reducer.AddPrivate args => Reducers.InvokeAddPrivate(eventContext, args),
Reducer.DeletePlayer args => Reducers.InvokeDeletePlayer(eventContext, args),
Reducer.DeletePlayersByName args => Reducers.InvokeDeletePlayersByName(eventContext, args),
Reducer.QueryPrivate args => Reducers.InvokeQueryPrivate(eventContext, args),
Reducer.RepeatingTest args => Reducers.InvokeRepeatingTest(eventContext, args),
Reducer.Test args => Reducers.InvokeTest(eventContext, args),
Reducer.TestBtreeIndexArgs args => Reducers.InvokeTestBtreeIndexArgs(eventContext, args),
Reducer.StdbNone or
Reducer.StdbIdentityConnected or
Reducer.StdbIdentityDisconnected => true,
+3 -3
View File
@@ -23,7 +23,7 @@ class Namespaces(Smoketest):
with tempfile.TemporaryDirectory() as tmpdir:
self.spacetime("generate", "--out-dir", tmpdir, "--lang=cs", "--project-path", self.project_path)
self.assertEqual(count_matches(tmpdir, f"namespace {namespace}"), 4)
self.assertEqual(count_matches(tmpdir, f"namespace {namespace}"), 2)
def test_custom_ns_csharp(self):
"""Ensure that when a custom namespace is specified on the command line, it actually gets used in generation"""
@@ -33,5 +33,5 @@ class Namespaces(Smoketest):
with tempfile.TemporaryDirectory() as tmpdir:
self.spacetime("generate", "--out-dir", tmpdir, "--lang=cs", "--namespace", namespace, "--project-path", self.project_path)
self.assertEqual(count_matches(tmpdir, f"namespace {namespace}"), 4)
self.assertEqual(count_matches(tmpdir, "using SpacetimeDB;"), 4)
self.assertEqual(count_matches(tmpdir, f"namespace {namespace}"), 2)
self.assertEqual(count_matches(tmpdir, "using SpacetimeDB;"), 2)