Skip to content

Commit bba6f89

Browse files
[C#] Adding RawModuleDefV10 to C# Module Bindings without Event Tables (#4288)
# Description of Changes This is the implementation of #4255 This is a rebuild of #4262 after a rebase throughly messed up that PR's changelog, this time under `master` branch. * Refactored `Module` so all V10 builder state and registration helpers now live on `partial class RawModuleDefV10`. The static `Module` class simply registers components against that builder and serializes via `moduleDef.BuildModuleDefinition()` * Removed the deprecated `__describe_module__` export. Only `__describe_module_v10__` is emitted now across the runtime, native shim, generated bindings, and snapshots * Mirrored the Rust TODO that future V10 sections will cover Event tables and Case-conversion policy so we don't lose track of those items Event Tables will be added once they are finished being implemented. # API and ABI breaking changes Modules built with these bindings now expose only `__describe_module_v10__` The legacy `__describe_module__` symbol is gone from both managed and native layers. Hosts expecting the old export must switch to the V10 entry point (which is already the canonical ABI for 2.0). # Expected complexity level and risk 2 - Low. The refactor keeps the previous builder logic but relocates it, and the export removal matches the already-supported V10 host path. # Testing - [X] Successfully built CLI and DLLs without errors. - [X] Ran `dotnet build crates/bindings-csharp/Runtime/Runtime.csproj` without errors. - [X] Ran `dotnet test crates/bindings-csharp/Codegen.Tests/Codegen.Tests.csproj` without errors. - [X] Ran `bash run-regression-tests.sh` without errors. --------- Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
1 parent 2ec07a3 commit bba6f89

10 files changed

Lines changed: 567 additions & 254 deletions

File tree

crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs

Lines changed: 217 additions & 114 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/bindings-csharp/Codegen.Tests/fixtures/server/Lib.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public partial record CustomTaggedEnum
9494
string? NullableStringVariant
9595
)>;
9696

97-
[SpacetimeDB.Table]
97+
[SpacetimeDB.Table(Event = true)]
9898
public partial class PrivateTable { }
9999

100100
[SpacetimeDB.Table(Public = true)]

crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs

Lines changed: 143 additions & 70 deletions
Large diffs are not rendered by default.

crates/bindings-csharp/Codegen/Module.cs

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ record TableAccessor
214214
{
215215
public readonly string Name;
216216
public readonly bool IsPublic;
217+
public readonly bool IsEvent;
217218
public readonly Scheduled? Scheduled;
218219

219220
public TableAccessor(TableDeclaration table, AttributeData data, DiagReporter diag)
@@ -222,6 +223,7 @@ public TableAccessor(TableDeclaration table, AttributeData data, DiagReporter di
222223

223224
Name = attr.Name ?? table.ShortName;
224225
IsPublic = attr.Public;
226+
IsEvent = attr.Event;
225227
if (
226228
attr.Scheduled is { } reducer
227229
&& table.GetColumnIndex(data, attr.ScheduledAt, diag) is { } scheduledAtIndex
@@ -388,7 +390,7 @@ public static bool CanParse(AttributeData data) =>
388390
public string GenerateIndexDef() =>
389391
$$"""
390392
new(
391-
Name: null,
393+
SourceName: null,
392394
AccessorName: "{{AccessorName}}",
393395
Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.{{Type}}([{{string.Join(
394396
", ",
@@ -732,8 +734,8 @@ public IEnumerable<GeneratedTableAccessor> GenerateTableAccessors()
732734
return row;
733735
}
734736
735-
public static SpacetimeDB.Internal.RawTableDefV9 MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new (
736-
Name: nameof({{{v.Name}}}),
737+
public static SpacetimeDB.Internal.RawTableDefV10 MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new (
738+
SourceName: nameof({{{v.Name}}}),
737739
ProductTypeRef: (uint) new {{{globalName}}}.BSATN().GetAlgebraicType(registrar).Ref_,
738740
PrimaryKey: [{{{GetPrimaryKey(v)?.ToString() ?? ""}}}],
739741
Indexes: [
@@ -747,14 +749,17 @@ public IEnumerable<GeneratedTableAccessor> GenerateTableAccessors()
747749
],
748750
Constraints: {{{GenConstraintList(v, ColumnAttrs.Unique, $"{iTable}.MakeUniqueConstraint")}}},
749751
Sequences: {{{GenConstraintList(v, ColumnAttrs.AutoInc, $"{iTable}.MakeSequence")}}},
750-
Schedule: {{{(
752+
TableType: SpacetimeDB.Internal.TableType.User,
753+
TableAccess: SpacetimeDB.Internal.TableAccess.{{{(v.IsPublic ? "Public" : "Private")}}},
754+
DefaultValues: [],
755+
IsEvent: {{{(v.IsEvent ? "true" : "false")}}}
756+
);
757+
758+
public static SpacetimeDB.Internal.RawScheduleDefV10? MakeScheduleDesc() => {{{(
751759
v.Scheduled is { } scheduled
752760
? $"{iTable}.MakeSchedule(\"{scheduled.ReducerName}\", {scheduled.ScheduledAtColumn})"
753761
: "null"
754-
)}}},
755-
TableType: SpacetimeDB.Internal.TableType.User,
756-
TableAccess: SpacetimeDB.Internal.TableAccess.{{{(v.IsPublic ? "Public" : "Private")}}}
757-
);
762+
)}}};
758763
759764
public ulong Count => {{{iTable}}}.DoCount();
760765
public IEnumerable<{{{globalName}}}> Iter() => {{{iTable}}}.DoIter();
@@ -1139,8 +1144,8 @@ method.ReturnType is INamedTypeSymbol
11391144

11401145
public string GenerateViewDef(uint Index) =>
11411146
$$$"""
1142-
new global::SpacetimeDB.Internal.RawViewDefV9(
1143-
Name: "{{{Name}}}",
1147+
new global::SpacetimeDB.Internal.RawViewDefV10(
1148+
SourceName: "{{{Name}}}",
11441149
Index: {{{Index}}},
11451150
IsPublic: {{{IsPublic.ToString().ToLower()}}},
11461151
IsAnonymous: {{{IsAnonymous.ToString().ToLower()}}},
@@ -1218,7 +1223,7 @@ public string GenerateDispatcherClass(uint index)
12181223
sealed class {{{Name}}}ViewDispatcher : {{{interfaceName}}} {
12191224
{{{MemberDeclaration.GenerateBsatnFields(Accessibility.Private, Parameters)}}}
12201225
1221-
public SpacetimeDB.Internal.RawViewDefV9 {{{makeViewDefMethod}}}(SpacetimeDB.BSATN.ITypeRegistrar registrar)
1226+
public SpacetimeDB.Internal.RawViewDefV10 {{{makeViewDefMethod}}}(SpacetimeDB.BSATN.ITypeRegistrar registrar)
12221227
=> {{{GenerateViewDef(index)}}}
12231228
12241229
public byte[] Invoke(
@@ -1305,17 +1310,21 @@ public string GenerateClass()
13051310
class {{Name}}: SpacetimeDB.Internal.IReducer {
13061311
{{MemberDeclaration.GenerateBsatnFields(Accessibility.Private, Args)}}
13071312
1308-
public SpacetimeDB.Internal.RawReducerDefV9 MakeReducerDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new (
1309-
nameof({{Name}}),
1310-
[{{MemberDeclaration.GenerateDefs(Args)}}],
1311-
{{Kind switch
1313+
public SpacetimeDB.Internal.RawReducerDefV10 MakeReducerDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new (
1314+
SourceName: nameof({{Name}}),
1315+
Params: [{{MemberDeclaration.GenerateDefs(Args)}}],
1316+
Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable,
1317+
OkReturnType: SpacetimeDB.BSATN.AlgebraicType.Unit,
1318+
ErrReturnType: new SpacetimeDB.BSATN.AlgebraicType.String(default)
1319+
);
1320+
1321+
public SpacetimeDB.Internal.Lifecycle? Lifecycle => {{Kind switch
13121322
{
13131323
ReducerKind.Init => "SpacetimeDB.Internal.Lifecycle.Init",
13141324
ReducerKind.ClientConnected => "SpacetimeDB.Internal.Lifecycle.OnConnect",
13151325
ReducerKind.ClientDisconnected => "SpacetimeDB.Internal.Lifecycle.OnDisconnect",
13161326
_ => "null"
1317-
}}}
1318-
);
1327+
}}};
13191328
13201329
public void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) {
13211330
{{invocation}};
@@ -1505,10 +1514,11 @@ public string GenerateClass()
15051514
class {{{Name}}} : SpacetimeDB.Internal.IProcedure {
15061515
{{{classFields}}}
15071516
1508-
public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new(
1509-
nameof({{{Name}}}),
1510-
[{{{MemberDeclaration.GenerateDefs(Args)}}}],
1511-
{{{returnTypeExpr}}}
1517+
public SpacetimeDB.Internal.RawProcedureDefV10 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new(
1518+
SourceName: nameof({{{Name}}}),
1519+
Params: [{{{MemberDeclaration.GenerateDefs(Args)}}}],
1520+
ReturnType: {{{returnTypeExpr}}},
1521+
Visibility: SpacetimeDB.Internal.FunctionVisibility.ClientCallable
15121522
);
15131523
15141524
public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) {

crates/bindings-csharp/Runtime/Attrs.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace SpacetimeDB
1+
namespace SpacetimeDB
22
{
33
namespace Internal
44
{
@@ -67,6 +67,8 @@ public sealed class TableAttribute : Attribute
6767
/// </summary>
6868
public bool Public { get; init; } = false;
6969

70+
public bool Event { get; init; } = false;
71+
7072
/// <summary>
7173
/// If set, the name of the reducer that will be invoked when the scheduled time is reached.
7274
/// </summary>

crates/bindings-csharp/Runtime/Internal/IReducer.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ public static Identity GetIdentity()
1414

1515
public interface IReducer
1616
{
17-
RawReducerDefV9 MakeReducerDef(ITypeRegistrar registrar);
17+
RawReducerDefV10 MakeReducerDef(ITypeRegistrar registrar);
18+
19+
Lifecycle? Lifecycle { get; }
1820

1921
// This one is not static because we need to be able to store IReducer in a list.
2022
void Invoke(BinaryReader reader, IReducerContext args);

crates/bindings-csharp/Runtime/Internal/ITable.cs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ public interface ITableView<View, T>
102102
where T : IStructuralReadWrite, new()
103103
{
104104
// These are the methods that codegen needs to implement.
105-
static abstract RawTableDefV9 MakeTableDesc(ITypeRegistrar registrar);
105+
static abstract RawTableDefV10 MakeTableDesc(ITypeRegistrar registrar);
106+
107+
static abstract RawScheduleDefV10? MakeScheduleDesc();
106108

107109
static abstract T ReadGenFields(BinaryReader reader, T row);
108110

@@ -179,19 +181,24 @@ out var out_
179181
return out_ > 0;
180182
}
181183

182-
protected static RawScheduleDefV9 MakeSchedule(string reducerName, ushort colIndex) =>
183-
new(Name: $"{tableName}_sched", ReducerName: reducerName, ScheduledAtColumn: colIndex);
184+
protected static RawScheduleDefV10 MakeSchedule(string reducerName, ushort colIndex) =>
185+
new(
186+
SourceName: null,
187+
TableName: tableName,
188+
ScheduleAtCol: colIndex,
189+
FunctionName: reducerName
190+
);
184191

185-
protected static RawSequenceDefV9 MakeSequence(ushort colIndex) =>
192+
protected static RawSequenceDefV10 MakeSequence(ushort colIndex) =>
186193
new(
187-
Name: null,
194+
SourceName: null,
188195
Column: colIndex,
189196
Start: null,
190197
MinValue: null,
191198
MaxValue: null,
192199
Increment: 1
193200
);
194201

195-
protected static RawConstraintDefV9 MakeUniqueConstraint(ushort colIndex) =>
196-
new(Name: null, Data: new RawConstraintDataV9.Unique(new([colIndex])));
202+
protected static RawConstraintDefV10 MakeUniqueConstraint(ushort colIndex) =>
203+
new(SourceName: null, Data: new RawConstraintDataV9.Unique(new([colIndex])));
197204
}

crates/bindings-csharp/Runtime/Internal/IView.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ namespace SpacetimeDB.Internal;
44

55
public interface IView
66
{
7-
RawViewDefV9 MakeViewDef(ITypeRegistrar registrar);
7+
RawViewDefV10 MakeViewDef(ITypeRegistrar registrar);
88

99
// This one is not static because we need to be able to store IView in a list.
1010
byte[] Invoke(BinaryReader reader, IViewContext args);
1111
}
1212

1313
public interface IAnonymousView
1414
{
15-
RawViewDefV9 MakeAnonymousViewDef(ITypeRegistrar registrar);
15+
RawViewDefV10 MakeAnonymousViewDef(ITypeRegistrar registrar);
1616

1717
// This one is not static because we need to be able to store IAnonymousView in a list.
1818
byte[] Invoke(BinaryReader reader, IAnonymousViewContext args);

0 commit comments

Comments
 (0)