Skip to content

Commit 023a7d3

Browse files
rekhoffbfops
andauthored
Add a SpacetimeDBException to C# SDK to aid in debugging (#3386)
# Description of Changes This implements a fix to an issue with debugging using the C# SDK, by adding new exception types: * `SpacetimeDBException`, * `SpacetimeDBArgumentException`, * `SpacetimeDBEmptyReducerNameException` Additional, regenerating bindings will now allow clients to report an `SpacetimeDBEmptyReducerNameException` rather than an `ArgumentOutOfRangeException` when the client receives an empty reducer name from the server. An example of the generated code currently, that results in the exception: https://github.com/clockworklabs/SpacetimeDB/blob/544e2edc2d1f7d1dd118832a815b6dbd7a6c1d82/sdks/csharp/examples~/quickstart-chat/client/module_bindings/SpacetimeDBClient.g.cs#L475 Note: Normally this is not an issue for a client, because the `SpacetimeDBEmptyReducerNameException` would be caught by the [Try/Catch](https://github.com/clockworklabs/SpacetimeDB/blob/9f59118e24449cdd2d3e182bd44fdb26078e921b/sdks/csharp/src/SpacetimeDBClient.cs#L421C25-L421C42) statement, but a debugger will still catch the exception and halt operation. This can be annoying to a developer when debugging. By separating out the exception into a custom `Exception` type, we allow a developer to flag the new exception type as something it can ignore, without ignoring other relevant exceptions. # API and ABI breaking changes Not a breaking change. Clients will need to regenerate bindings to get the new exceptions # Expected complexity level and risk 1 # Testing - [X] Tested regenerating bindings and confirmed intended output. - [X] Tested debugging and receiving `SpacetimeDBEmptyReducerNameException` when expected. --------- Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
1 parent 230205d commit 023a7d3

File tree

9 files changed

+160
-1
lines changed

9 files changed

+160
-1
lines changed

crates/codegen/src/csharp.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,10 @@ impl Lang for Csharp<'_> {
789789
"\"{reducer_str_name}\" => BSATNHelpers.Decode<Reducer.{reducer_name}>(encodedArgs),"
790790
);
791791
}
792+
writeln!(
793+
output,
794+
r#""" => throw new SpacetimeDBEmptyReducerNameException("Reducer name is empty"),"#
795+
);
792796
writeln!(
793797
output,
794798
r#"var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {{reducer}}")"#

crates/codegen/tests/snapshots/codegen__codegen_csharp.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
source: crates/codegen/tests/codegen.rs
3+
assertion_line: 37
34
expression: outfiles
45
---
56
"Reducers/Add.g.cs" = '''
@@ -1463,6 +1464,7 @@ namespace SpacetimeDB
14631464
"say_hello" => BSATNHelpers.Decode<Reducer.SayHello>(encodedArgs),
14641465
"test" => BSATNHelpers.Decode<Reducer.Test>(encodedArgs),
14651466
"test_btree_index_args" => BSATNHelpers.Decode<Reducer.TestBtreeIndexArgs>(encodedArgs),
1467+
"" => throw new SpacetimeDBEmptyReducerNameException("Reducer name is empty"),
14661468
var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}")
14671469
};
14681470
}

demo/Blackholio/client-unity/Assets/Scripts/autogen/SpacetimeDBClient.g.cs

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdks/csharp/examples~/quickstart-chat/client/module_bindings/SpacetimeDBClient.g.cs

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdks/csharp/examples~/regression-tests/republishing/client/client.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11-
<PackageReference Include="SpacetimeDB.ClientSDK" Version="1.5.0" />
11+
<ProjectReference Include="../../../../SpacetimeDB.ClientSDK.csproj" />
1212
</ItemGroup>
1313

1414
</Project>

sdks/csharp/examples~/regression-tests/republishing/client/module_bindings/SpacetimeDBClient.g.cs

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdks/csharp/src/Exceptions.cs

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
using System;
2+
using System.Runtime.Serialization;
3+
4+
namespace SpacetimeDB
5+
{
6+
/// <summary>
7+
/// The base class for all SpacetimeDB SDK exceptions.
8+
/// This allows users to catch all SpacetimeDB-specific exceptions in one catch block
9+
/// or configure their debugger to ignore them.
10+
/// </summary>
11+
[Serializable]
12+
public class SpacetimeDBException : Exception
13+
{
14+
// Base HRESULT for SpacetimeDB exceptions (0x8A000000 is in the user-defined range)
15+
private const int SPACETIMEDB_HRESULT_BASE = unchecked((int)0x8A000000);
16+
17+
// Specific HRESULTs for different exception types
18+
public const int SPACETIMEDB_EMPTY_REDUCER_NAME = SPACETIMEDB_HRESULT_BASE + 1;
19+
20+
public SpacetimeDBException()
21+
: base()
22+
{
23+
HResult = SPACETIMEDB_HRESULT_BASE;
24+
}
25+
26+
public SpacetimeDBException(string? message)
27+
: base(message)
28+
{
29+
HResult = SPACETIMEDB_HRESULT_BASE;
30+
}
31+
32+
public SpacetimeDBException(string? message, Exception? innerException)
33+
: base(message, innerException)
34+
{
35+
HResult = SPACETIMEDB_HRESULT_BASE;
36+
}
37+
38+
protected SpacetimeDBException(SerializationInfo info, StreamingContext context)
39+
: base(info, context) { }
40+
}
41+
42+
/// <summary>
43+
/// The exception that is thrown when one of the arguments provided to a method is not valid.
44+
/// This is the base class for all SpacetimeDB argument exceptions.
45+
/// </summary>
46+
[Serializable]
47+
public class SpacetimeDBArgumentException : SpacetimeDBException
48+
{
49+
private readonly string? _paramName;
50+
51+
public SpacetimeDBArgumentException()
52+
: base("Value does not fall within the expected range.") { }
53+
54+
public SpacetimeDBArgumentException(string? message)
55+
: base(message) { }
56+
57+
public SpacetimeDBArgumentException(string? message, Exception? innerException)
58+
: base(message, innerException) { }
59+
60+
public SpacetimeDBArgumentException(
61+
string? message,
62+
string? paramName,
63+
Exception? innerException
64+
)
65+
: base(message, innerException)
66+
{
67+
_paramName = paramName;
68+
}
69+
70+
public SpacetimeDBArgumentException(string? message, string? paramName)
71+
: base(message)
72+
{
73+
_paramName = paramName;
74+
}
75+
76+
protected SpacetimeDBArgumentException(SerializationInfo info, StreamingContext context)
77+
: base(info, context)
78+
{
79+
_paramName = info.GetString("ParamName");
80+
}
81+
82+
public override void GetObjectData(SerializationInfo info, StreamingContext context)
83+
{
84+
base.GetObjectData(info, context);
85+
info.AddValue("ParamName", _paramName, typeof(string));
86+
}
87+
88+
public virtual string? ParamName => _paramName;
89+
}
90+
91+
/// <summary>
92+
/// The exception that is thrown when an empty reducer name is received from the server.
93+
/// This is a known condition that is handled internally by the SpacetimeDB client.
94+
/// </summary>
95+
[Serializable]
96+
public class SpacetimeDBEmptyReducerNameException : SpacetimeDBArgumentException
97+
{
98+
public SpacetimeDBEmptyReducerNameException()
99+
: base("Empty reducer name received from server", (string?)null)
100+
{
101+
HResult = SPACETIMEDB_EMPTY_REDUCER_NAME;
102+
}
103+
104+
public SpacetimeDBEmptyReducerNameException(string? paramName)
105+
: base("Empty reducer name received from server", paramName)
106+
{
107+
HResult = SPACETIMEDB_EMPTY_REDUCER_NAME;
108+
}
109+
110+
public SpacetimeDBEmptyReducerNameException(string? message, string? paramName)
111+
: base(message, paramName)
112+
{
113+
HResult = SPACETIMEDB_EMPTY_REDUCER_NAME;
114+
}
115+
116+
public SpacetimeDBEmptyReducerNameException(string? message, Exception? innerException)
117+
: base(message, null, innerException)
118+
{
119+
HResult = SPACETIMEDB_EMPTY_REDUCER_NAME;
120+
}
121+
122+
public SpacetimeDBEmptyReducerNameException(
123+
string? message,
124+
string? paramName,
125+
Exception? innerException
126+
)
127+
: base(message, paramName, innerException)
128+
{
129+
HResult = SPACETIMEDB_EMPTY_REDUCER_NAME;
130+
}
131+
132+
protected SpacetimeDBEmptyReducerNameException(
133+
SerializationInfo info,
134+
StreamingContext context
135+
)
136+
: base(info, context) { }
137+
}
138+
}

sdks/csharp/src/Exceptions.cs.meta

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

0 commit comments

Comments
 (0)