Skip to content

Commit eeb3333

Browse files
authored
Implement OnUnhandledReducerError in C# (#2636)
1 parent 118e59d commit eeb3333

File tree

2 files changed

+261
-17
lines changed

2 files changed

+261
-17
lines changed

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

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ use std::path::PathBuf;
2727
const INDENT: &str = " ";
2828

2929
const REDUCER_EVENTS: &str = r#"
30-
public interface IRemoteDbContext : IDbContext<RemoteTables, RemoteReducers, SetReducerFlags, SubscriptionBuilder> { }
30+
public interface IRemoteDbContext : IDbContext<RemoteTables, RemoteReducers, SetReducerFlags, SubscriptionBuilder> {
31+
public event Action<ReducerEventContext, Exception>? OnUnhandledReducerError;
32+
}
3133
3234
public sealed class EventContext : IEventContext, IRemoteDbContext
3335
{
@@ -88,6 +90,13 @@ const REDUCER_EVENTS: &str = r#"
8890
/// Get this connection's <c>ConnectionId</c>.
8991
/// </summary>
9092
public ConnectionId ConnectionId => conn.ConnectionId;
93+
/// <summary>
94+
/// Register a callback to be called when a reducer with no handler returns an error.
95+
/// </summary>
96+
public event Action<ReducerEventContext, Exception>? OnUnhandledReducerError {
97+
add => Reducers.InternalOnUnhandledReducerError += value;
98+
remove => Reducers.InternalOnUnhandledReducerError -= value;
99+
}
91100
92101
internal EventContext(DbConnection conn, Event<Reducer> Event)
93102
{
@@ -154,6 +163,13 @@ const REDUCER_EVENTS: &str = r#"
154163
/// Get this connection's <c>ConnectionId</c>.
155164
/// </summary>
156165
public ConnectionId ConnectionId => conn.ConnectionId;
166+
/// <summary>
167+
/// Register a callback to be called when a reducer with no handler returns an error.
168+
/// </summary>
169+
public event Action<ReducerEventContext, Exception>? OnUnhandledReducerError {
170+
add => Reducers.InternalOnUnhandledReducerError += value;
171+
remove => Reducers.InternalOnUnhandledReducerError -= value;
172+
}
157173
158174
internal ReducerEventContext(DbConnection conn, ReducerEvent<Reducer> reducerEvent)
159175
{
@@ -225,6 +241,13 @@ const REDUCER_EVENTS: &str = r#"
225241
/// Get this connection's <c>ConnectionId</c>.
226242
/// </summary>
227243
public ConnectionId ConnectionId => conn.ConnectionId;
244+
/// <summary>
245+
/// Register a callback to be called when a reducer with no handler returns an error.
246+
/// </summary>
247+
public event Action<ReducerEventContext, Exception>? OnUnhandledReducerError {
248+
add => Reducers.InternalOnUnhandledReducerError += value;
249+
remove => Reducers.InternalOnUnhandledReducerError -= value;
250+
}
228251
229252
internal ErrorContext(DbConnection conn, Exception error)
230253
{
@@ -287,6 +310,13 @@ const REDUCER_EVENTS: &str = r#"
287310
/// Get this connection's <c>ConnectionId</c>.
288311
/// </summary>
289312
public ConnectionId ConnectionId => conn.ConnectionId;
313+
/// <summary>
314+
/// Register a callback to be called when a reducer with no handler returns an error.
315+
/// </summary>
316+
public event Action<ReducerEventContext, Exception>? OnUnhandledReducerError {
317+
add => Reducers.InternalOnUnhandledReducerError += value;
318+
remove => Reducers.InternalOnUnhandledReducerError -= value;
319+
}
290320
291321
internal SubscriptionEventContext(DbConnection conn)
292322
{
@@ -639,7 +669,19 @@ impl Lang for Csharp<'_> {
639669
"public bool Invoke{func_name_pascal_case}(ReducerEventContext ctx, Reducer.{func_name_pascal_case} args)"
640670
);
641671
indented_block(output, |output| {
642-
writeln!(output, "if (On{func_name_pascal_case} == null) return false;");
672+
writeln!(output, "if (On{func_name_pascal_case} == null)");
673+
indented_block(output, |output| {
674+
writeln!(output, "if (InternalOnUnhandledReducerError != null)");
675+
indented_block(output, |output| {
676+
writeln!(output, "switch(ctx.Event.Status)");
677+
indented_block(output, |output| {
678+
writeln!(output, "case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break;");
679+
writeln!(output, "case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception(\"out of energy\")); break;");
680+
});
681+
});
682+
writeln!(output, "return false;");
683+
});
684+
643685
writeln!(output, "On{func_name_pascal_case}(");
644686
// Write out arguments one per line
645687
{
@@ -706,6 +748,10 @@ impl Lang for Csharp<'_> {
706748
"internal RemoteReducers(DbConnection conn, SetReducerFlags flags) : base(conn) => SetCallReducerFlags = flags;"
707749
);
708750
writeln!(output, "internal readonly SetReducerFlags SetCallReducerFlags;");
751+
writeln!(
752+
output,
753+
"internal event Action<ReducerEventContext, Exception>? InternalOnUnhandledReducerError;"
754+
)
709755
});
710756
writeln!(output);
711757

@@ -828,6 +874,14 @@ impl Lang for Csharp<'_> {
828874
writeln!(output);
829875

830876
writeln!(output, "public SubscriptionBuilder SubscriptionBuilder() => new(this);");
877+
writeln!(
878+
output,
879+
"public event Action<ReducerEventContext, Exception> OnUnhandledReducerError"
880+
);
881+
indented_block(output, |output| {
882+
writeln!(output, "add => Reducers.InternalOnUnhandledReducerError += value;");
883+
writeln!(output, "remove => Reducers.InternalOnUnhandledReducerError -= value;");
884+
});
831885
});
832886

833887
vec![("SpacetimeDBClient.g.cs".to_owned(), output.into_inner())]

0 commit comments

Comments
 (0)