From 5eb23cb79f97b0cb87c0f71d7b1aeedb0b358213 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 12 Nov 2024 16:09:13 +0100 Subject: [PATCH] implement websocket ids-no-names (take 2) in c# --- examples~/quickstart/client/client.csproj | 1 + .../IdentityConnectedReducer.cs | 17 ++++ .../IdentityDisconnectedReducer.cs | 17 ++++ .../client/module_bindings/InitReducer.cs | 17 ++++ .../_Globals/SpacetimeDBClient.cs | 94 +++++++++++++++---- src/SpacetimeDB/ClientApi/AfterConnecting.cs | 35 +++++++ src/SpacetimeDB/ClientApi/CallReducer.cs | 9 +- src/SpacetimeDB/ClientApi/IdsToNames.cs | 45 +++++++++ src/SpacetimeDB/ClientApi/OneOffTable.cs | 9 +- src/SpacetimeDB/ClientApi/ReducerCallInfo.cs | 5 - src/SpacetimeDB/ClientApi/ServerMessage.cs | 2 +- src/SpacetimeDB/ClientApi/TableUpdate.cs | 5 - src/SpacetimeDBClient.cs | 69 +++++++++++--- tests~/SnapshotTests.cs | 49 +++++----- 14 files changed, 297 insertions(+), 77 deletions(-) create mode 100644 examples~/quickstart/client/module_bindings/IdentityConnectedReducer.cs create mode 100644 examples~/quickstart/client/module_bindings/IdentityDisconnectedReducer.cs create mode 100644 examples~/quickstart/client/module_bindings/InitReducer.cs create mode 100644 src/SpacetimeDB/ClientApi/AfterConnecting.cs create mode 100644 src/SpacetimeDB/ClientApi/IdsToNames.cs diff --git a/examples~/quickstart/client/client.csproj b/examples~/quickstart/client/client.csproj index 93444533..48917cce 100644 --- a/examples~/quickstart/client/client.csproj +++ b/examples~/quickstart/client/client.csproj @@ -3,6 +3,7 @@ Exe net7.0 + false disable enable diff --git a/examples~/quickstart/client/module_bindings/IdentityConnectedReducer.cs b/examples~/quickstart/client/module_bindings/IdentityConnectedReducer.cs new file mode 100644 index 00000000..de74d98d --- /dev/null +++ b/examples~/quickstart/client/module_bindings/IdentityConnectedReducer.cs @@ -0,0 +1,17 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; + +namespace SpacetimeDB.Types +{ + [SpacetimeDB.Type] + public partial class IdentityConnected : IReducerArgs + { + string IReducerArgs.ReducerName => "__identity_connected__"; + } +} diff --git a/examples~/quickstart/client/module_bindings/IdentityDisconnectedReducer.cs b/examples~/quickstart/client/module_bindings/IdentityDisconnectedReducer.cs new file mode 100644 index 00000000..e52e95ee --- /dev/null +++ b/examples~/quickstart/client/module_bindings/IdentityDisconnectedReducer.cs @@ -0,0 +1,17 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; + +namespace SpacetimeDB.Types +{ + [SpacetimeDB.Type] + public partial class IdentityDisconnected : IReducerArgs + { + string IReducerArgs.ReducerName => "__identity_disconnected__"; + } +} diff --git a/examples~/quickstart/client/module_bindings/InitReducer.cs b/examples~/quickstart/client/module_bindings/InitReducer.cs new file mode 100644 index 00000000..4765f0e4 --- /dev/null +++ b/examples~/quickstart/client/module_bindings/InitReducer.cs @@ -0,0 +1,17 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN RUST INSTEAD. +// + +#nullable enable + +using System; +using SpacetimeDB; + +namespace SpacetimeDB.Types +{ + [SpacetimeDB.Type] + public partial class Init : IReducerArgs + { + string IReducerArgs.ReducerName => "__init__"; + } +} diff --git a/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs b/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs index 726f56d0..21936ac7 100644 --- a/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs +++ b/examples~/quickstart/client/module_bindings/_Globals/SpacetimeDBClient.cs @@ -25,30 +25,30 @@ internal MessageHandle() public class UserHandle : RemoteTableHandle { - private static Dictionary Identity_Index = new(16); public override void InternalInvokeValueInserted(IDatabaseRow row) { var value = (User)row; - Identity_Index[value.Identity] = value; + Identity.Cache[value.Identity] = value; } public override void InternalInvokeValueDeleted(IDatabaseRow row) { - Identity_Index.Remove(((User)row).Identity); + Identity.Cache.Remove(((User)row).Identity); } - public readonly ref struct IdentityUniqueIndex + public class IdentityUniqueIndex { + internal readonly Dictionary Cache = new(16); public User? Find(SpacetimeDB.Identity value) { - Identity_Index.TryGetValue(value, out var r); + Cache.TryGetValue(value, out var r); return r; } } - public IdentityUniqueIndex Identity => new(); + public IdentityUniqueIndex Identity = new(); internal UserHandle() { @@ -65,6 +65,54 @@ public sealed class RemoteReducers : RemoteBase { internal RemoteReducers(DbConnection conn, SetReducerFlags SetReducerFlags) : base(conn) { this.SetCallReducerFlags = SetReducerFlags; } internal readonly SetReducerFlags SetCallReducerFlags; + public delegate void IdentityConnectedHandler(EventContext ctx); + public event IdentityConnectedHandler? OnIdentityConnected; + + public void IdentityConnected() + { + conn.InternalCallReducer(new IdentityConnected { }, this.SetCallReducerFlags.IdentityConnectedFlags); + } + + public bool InvokeIdentityConnected(EventContext ctx, IdentityConnected args) + { + if (OnIdentityConnected == null) return false; + OnIdentityConnected( + ctx + ); + return true; + } + public delegate void IdentityDisconnectedHandler(EventContext ctx); + public event IdentityDisconnectedHandler? OnIdentityDisconnected; + + public void IdentityDisconnected() + { + conn.InternalCallReducer(new IdentityDisconnected { }, this.SetCallReducerFlags.IdentityDisconnectedFlags); + } + + public bool InvokeIdentityDisconnected(EventContext ctx, IdentityDisconnected args) + { + if (OnIdentityDisconnected == null) return false; + OnIdentityDisconnected( + ctx + ); + return true; + } + public delegate void InitHandler(EventContext ctx); + public event InitHandler? OnInit; + + public void Init() + { + conn.InternalCallReducer(new Init { }, this.SetCallReducerFlags.InitFlags); + } + + public bool InvokeInit(EventContext ctx, Init args) + { + if (OnInit == null) return false; + OnInit( + ctx + ); + return true; + } public delegate void SendMessageHandler(EventContext ctx, string text); public event SendMessageHandler? OnSendMessage; @@ -104,6 +152,12 @@ public bool InvokeSetName(EventContext ctx, SetName args) public sealed class SetReducerFlags { internal SetReducerFlags() { } + internal CallReducerFlags IdentityConnectedFlags; + public void IdentityConnected(CallReducerFlags flags) { this.IdentityConnectedFlags = flags; } + internal CallReducerFlags IdentityDisconnectedFlags; + public void IdentityDisconnected(CallReducerFlags flags) { this.IdentityDisconnectedFlags = flags; } + internal CallReducerFlags InitFlags; + public void Init(CallReducerFlags flags) { this.InitFlags = flags; } internal CallReducerFlags SendMessageFlags; public void SendMessage(CallReducerFlags flags) { this.SendMessageFlags = flags; } internal CallReducerFlags SetNameFlags; @@ -126,11 +180,12 @@ internal EventContext(DbConnection conn, Event reducerEvent) : base(con [Type] public partial record Reducer : TaggedEnum<( + IdentityConnected IdentityConnected, + IdentityDisconnected IdentityDisconnected, + Init Init, SendMessage SendMessage, SetName SetName, - Unit StdbNone, - Unit StdbIdentityConnected, - Unit StdbIdentityDisconnected + Unit StdbNone )>; public class DbConnection : DbConnectionBase { @@ -147,17 +202,16 @@ public DbConnection() clientDB.AddTable("user", Db.User); } - protected override Reducer ToReducer(TransactionUpdate update) + protected override Reducer ToReducer(string reducerName, TransactionUpdate update) { var encodedArgs = update.ReducerCall.Args; - return update.ReducerCall.ReducerName switch - { + return reducerName switch { + "__identity_connected__" => new Reducer.IdentityConnected(BSATNHelpers.Decode(encodedArgs)), + "__identity_disconnected__" => new Reducer.IdentityDisconnected(BSATNHelpers.Decode(encodedArgs)), + "__init__" => new Reducer.Init(BSATNHelpers.Decode(encodedArgs)), "send_message" => new Reducer.SendMessage(BSATNHelpers.Decode(encodedArgs)), "set_name" => new Reducer.SetName(BSATNHelpers.Decode(encodedArgs)), "" => new Reducer.StdbNone(default), - "__identity_connected__" => new Reducer.StdbIdentityConnected(default), - "__identity_disconnected__" => new Reducer.StdbIdentityDisconnected(default), - "" => new Reducer.StdbNone(default), var reducer => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") }; } @@ -168,13 +222,13 @@ protected override IEventContext ToEventContext(Event reducerEvent) => protected override bool Dispatch(IEventContext context, Reducer reducer) { var eventContext = (EventContext)context; - return reducer switch - { + return reducer switch { + Reducer.IdentityConnected(var args) => Reducers.InvokeIdentityConnected(eventContext, args), + Reducer.IdentityDisconnected(var args) => Reducers.InvokeIdentityDisconnected(eventContext, args), + Reducer.Init(var args) => Reducers.InvokeInit(eventContext, args), Reducer.SendMessage(var args) => Reducers.InvokeSendMessage(eventContext, args), Reducer.SetName(var args) => Reducers.InvokeSetName(eventContext, args), - Reducer.StdbNone or - Reducer.StdbIdentityConnected or - Reducer.StdbIdentityDisconnected => true, + Reducer.StdbNone => true, _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") }; } diff --git a/src/SpacetimeDB/ClientApi/AfterConnecting.cs b/src/SpacetimeDB/ClientApi/AfterConnecting.cs new file mode 100644 index 00000000..a141c3f0 --- /dev/null +++ b/src/SpacetimeDB/ClientApi/AfterConnecting.cs @@ -0,0 +1,35 @@ +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public partial class AfterConnecting + { + [DataMember(Name = "identity_token")] + public SpacetimeDB.ClientApi.IdentityToken IdentityToken; + [DataMember(Name = "ids_to_names")] + public SpacetimeDB.ClientApi.IdsToNames IdsToNames; + + public AfterConnecting( + SpacetimeDB.ClientApi.IdentityToken IdentityToken, + SpacetimeDB.ClientApi.IdsToNames IdsToNames + ) + { + this.IdentityToken = IdentityToken; + this.IdsToNames = IdsToNames; + } + + public AfterConnecting() + { + this.IdentityToken = new(); + this.IdsToNames = new(); + } + + } +} diff --git a/src/SpacetimeDB/ClientApi/CallReducer.cs b/src/SpacetimeDB/ClientApi/CallReducer.cs index 212d9bb3..be60a49a 100644 --- a/src/SpacetimeDB/ClientApi/CallReducer.cs +++ b/src/SpacetimeDB/ClientApi/CallReducer.cs @@ -15,8 +15,8 @@ namespace SpacetimeDB.ClientApi [DataContract] public partial class CallReducer { - [DataMember(Name = "reducer")] - public string Reducer; + [DataMember(Name = "reducer_id")] + public uint ReducerId; [DataMember(Name = "args")] public byte[] Args; [DataMember(Name = "request_id")] @@ -25,13 +25,13 @@ public partial class CallReducer public byte Flags; public CallReducer( - string Reducer, + uint ReducerId, byte[] Args, uint RequestId, byte Flags ) { - this.Reducer = Reducer; + this.ReducerId = ReducerId; this.Args = Args; this.RequestId = RequestId; this.Flags = Flags; @@ -39,7 +39,6 @@ byte Flags public CallReducer() { - this.Reducer = ""; this.Args = Array.Empty(); } diff --git a/src/SpacetimeDB/ClientApi/IdsToNames.cs b/src/SpacetimeDB/ClientApi/IdsToNames.cs new file mode 100644 index 00000000..f9f2e0f4 --- /dev/null +++ b/src/SpacetimeDB/ClientApi/IdsToNames.cs @@ -0,0 +1,45 @@ +#nullable enable + +using System; +using SpacetimeDB; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.ClientApi +{ + [SpacetimeDB.Type] + [DataContract] + public partial class IdsToNames + { + [DataMember(Name = "reducer_ids")] + public System.Collections.Generic.List ReducerIds; + [DataMember(Name = "reducer_names")] + public System.Collections.Generic.List ReducerNames; + [DataMember(Name = "table_ids")] + public System.Collections.Generic.List TableIds; + [DataMember(Name = "table_names")] + public System.Collections.Generic.List TableNames; + + public IdsToNames( + System.Collections.Generic.List ReducerIds, + System.Collections.Generic.List ReducerNames, + System.Collections.Generic.List TableIds, + System.Collections.Generic.List TableNames + ) + { + this.ReducerIds = ReducerIds; + this.ReducerNames = ReducerNames; + this.TableIds = TableIds; + this.TableNames = TableNames; + } + + public IdsToNames() + { + ReducerIds = new(); + ReducerNames = new(); + TableIds = new(); + TableNames = new(); + } + + } +} diff --git a/src/SpacetimeDB/ClientApi/OneOffTable.cs b/src/SpacetimeDB/ClientApi/OneOffTable.cs index fe667b18..e7d9f5a9 100644 --- a/src/SpacetimeDB/ClientApi/OneOffTable.cs +++ b/src/SpacetimeDB/ClientApi/OneOffTable.cs @@ -15,23 +15,22 @@ namespace SpacetimeDB.ClientApi [DataContract] public partial class OneOffTable { - [DataMember(Name = "table_name")] - public string TableName; + [DataMember(Name = "table_id")] + public uint TableId; [DataMember(Name = "rows")] public SpacetimeDB.ClientApi.BsatnRowList Rows; public OneOffTable( - string TableName, + uint TableId, SpacetimeDB.ClientApi.BsatnRowList Rows ) { - this.TableName = TableName; + this.TableId = TableId; this.Rows = Rows; } public OneOffTable() { - this.TableName = ""; this.Rows = new(); } diff --git a/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs b/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs index f8acaffd..665112f2 100644 --- a/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs +++ b/src/SpacetimeDB/ClientApi/ReducerCallInfo.cs @@ -15,8 +15,6 @@ namespace SpacetimeDB.ClientApi [DataContract] public partial class ReducerCallInfo { - [DataMember(Name = "reducer_name")] - public string ReducerName; [DataMember(Name = "reducer_id")] public uint ReducerId; [DataMember(Name = "args")] @@ -25,13 +23,11 @@ public partial class ReducerCallInfo public uint RequestId; public ReducerCallInfo( - string ReducerName, uint ReducerId, byte[] Args, uint RequestId ) { - this.ReducerName = ReducerName; this.ReducerId = ReducerId; this.Args = Args; this.RequestId = RequestId; @@ -39,7 +35,6 @@ uint RequestId public ReducerCallInfo() { - this.ReducerName = ""; this.Args = Array.Empty(); } diff --git a/src/SpacetimeDB/ClientApi/ServerMessage.cs b/src/SpacetimeDB/ClientApi/ServerMessage.cs index f66fdd98..d7b9f9a8 100644 --- a/src/SpacetimeDB/ClientApi/ServerMessage.cs +++ b/src/SpacetimeDB/ClientApi/ServerMessage.cs @@ -14,7 +14,7 @@ public partial record ServerMessage : SpacetimeDB.TaggedEnum<( SpacetimeDB.ClientApi.InitialSubscription InitialSubscription, SpacetimeDB.ClientApi.TransactionUpdate TransactionUpdate, SpacetimeDB.ClientApi.TransactionUpdateLight TransactionUpdateLight, - SpacetimeDB.ClientApi.IdentityToken IdentityToken, + SpacetimeDB.ClientApi.AfterConnecting AfterConnecting, SpacetimeDB.ClientApi.OneOffQueryResponse OneOffQueryResponse )>; } diff --git a/src/SpacetimeDB/ClientApi/TableUpdate.cs b/src/SpacetimeDB/ClientApi/TableUpdate.cs index d3265065..157c440c 100644 --- a/src/SpacetimeDB/ClientApi/TableUpdate.cs +++ b/src/SpacetimeDB/ClientApi/TableUpdate.cs @@ -17,8 +17,6 @@ public partial class TableUpdate { [DataMember(Name = "table_id")] public uint TableId; - [DataMember(Name = "table_name")] - public string TableName; [DataMember(Name = "num_rows")] public ulong NumRows; [DataMember(Name = "updates")] @@ -26,20 +24,17 @@ public partial class TableUpdate public TableUpdate( uint TableId, - string TableName, ulong NumRows, System.Collections.Generic.List Updates ) { this.TableId = TableId; - this.TableName = TableName; this.NumRows = NumRows; this.Updates = Updates; } public TableUpdate() { - this.TableName = ""; this.Updates = new(); } diff --git a/src/SpacetimeDBClient.cs b/src/SpacetimeDBClient.cs index c9d7d704..846733e1 100644 --- a/src/SpacetimeDBClient.cs +++ b/src/SpacetimeDBClient.cs @@ -39,7 +39,7 @@ public DbConnection Build() #if UNITY_5_3_OR_NEWER if (SpacetimeDBNetworkManager._instance != null) { - SpacetimeDBNetworkManager._instance.AddConnection(conn); + SpacetimeDBNetworkManager._instance.AddConnection(conn); } #endif return conn; @@ -150,7 +150,7 @@ struct DbOp private bool connectionClosed; protected readonly ClientCache clientDB; - protected abstract Reducer ToReducer(TransactionUpdate update); + protected abstract Reducer ToReducer(string reducerName, TransactionUpdate update); protected abstract IEventContext ToEventContext(Event reducerEvent); private readonly Dictionary> waitingOneOffQueries = new(); @@ -159,6 +159,27 @@ struct DbOp private readonly Thread networkMessageProcessThread; public readonly Stats stats = new(); + private Dictionary reducerIdToName = new(); + private Dictionary reducerNameToId = new(); + private Dictionary tableIdToName = new(); + private void InitIds(IdsToNames idsToNames) + { + for (int idx = 0; idx < idsToNames.ReducerIds.Count; idx++) + { + var id = idsToNames.ReducerIds[idx]; + var name = idsToNames.ReducerNames[idx]; + reducerIdToName.Add(id, name); + reducerNameToId.Add(name, id); + } + for (int idx = 0; idx < idsToNames.TableIds.Count; idx++) + { + var id = idsToNames.TableIds[idx]; + var name = idsToNames.TableNames[idx]; + tableIdToName.Add(id, name); + } + } + private string TableIdToName(uint tableId) => tableIdToName[tableId]; + protected DbConnectionBase() { clientDB = new(this); @@ -177,8 +198,8 @@ protected DbConnectionBase() { if (SpacetimeDBNetworkManager._instance != null) { - SpacetimeDBNetworkManager._instance.RemoveConnection(this); - } + SpacetimeDBNetworkManager._instance.RemoveConnection(this); + } }; #endif @@ -351,7 +372,7 @@ void PreProcessMessages() { foreach (var update in updates.Tables) { - var tableName = update.TableName; + var tableName = tableIdToName[update.TableId]; var table = clientDB.GetTable(tableName); if (table == null) { @@ -446,7 +467,7 @@ List PreProcessDatabaseUpdate(DatabaseUpdate updates) { if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) { - Log.Warn($"Update with the same primary key was applied multiple times! tableName={update.TableName}"); + Log.Warn($"Update with the same primary key was applied multiple times! tableName={TableIdToName(update.TableId)}"); // TODO(jdetter): Is this a correctable error? This would be a major error on the // SpacetimeDB side. continue; @@ -481,7 +502,7 @@ List PreProcessDatabaseUpdate(DatabaseUpdate updates) { if ((op.insert is not null && oldOp.insert is not null) || (op.delete is not null && oldOp.delete is not null)) { - Log.Warn($"Update with the same primary key was applied multiple times! tableName={update.TableName}"); + Log.Warn($"Update with the same primary key was applied multiple times! tableName={TableIdToName(update.TableId)}"); // TODO(jdetter): Is this a correctable error? This would be a major error on the // SpacetimeDB side. continue; @@ -547,6 +568,17 @@ PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) // Convert the generic event arguments in to a domain specific event object try { + var reducerId = transactionUpdate.ReducerCall.ReducerId; + string reducerName; + if (reducerId == 4294967295) // u32::MAX () + { + reducerName = ""; + } + else + { + reducerName = reducerIdToName[reducerId]; + } + reducerEvent = new( DateTimeOffset.FromUnixTimeMilliseconds((long)transactionUpdate.Timestamp.Microseconds / 1000), transactionUpdate.Status switch @@ -559,7 +591,8 @@ PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) transactionUpdate.CallerIdentity, transactionUpdate.CallerAddress, transactionUpdate.EnergyQuantaUsed.Quanta, - ToReducer(transactionUpdate)); + ToReducer(reducerName, transactionUpdate) + ); } catch (Exception e) { @@ -574,7 +607,8 @@ PreProcessedMessage PreProcessMessage(UnprocessedMessage unprocessed) case ServerMessage.TransactionUpdateLight(var update): dbOps = PreProcessDatabaseUpdate(update.Update); break; - case ServerMessage.IdentityToken(var identityToken): + case ServerMessage.AfterConnecting(var afterConnecting): + InitIds(afterConnecting.IdsToNames); break; case ServerMessage.OneOffQueryResponse(var resp): PreProcessOneOffQuery(resp); @@ -793,7 +827,7 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) case ServerMessage.TransactionUpdate(var transactionUpdate): { - var reducer = transactionUpdate.ReducerCall.ReducerName; + var reducer = reducerIdToName[transactionUpdate.ReducerCall.ReducerId]; stats.ParseMessageTracker.InsertRequest(timestamp, $"type={nameof(ServerMessage.TransactionUpdate)},reducer={reducer}"); var hostDuration = TimeSpan.FromMilliseconds(transactionUpdate.HostExecutionDurationMicros / 1000.0d); stats.AllReducersTracker.InsertRequest(hostDuration, $"reducer={reducer}"); @@ -840,9 +874,10 @@ private void OnMessageProcessComplete(PreProcessedMessage preProcessed) } break; } - case ServerMessage.IdentityToken(var identityToken): + case ServerMessage.AfterConnecting(var afterConnecting): try { + var identityToken = afterConnecting.IdentityToken; Identity = identityToken.Identity; onConnect?.Invoke(identityToken.Identity, identityToken.Token); } @@ -875,10 +910,13 @@ public void InternalCallReducer(T args, CallReducerFlags flags) return; } + var reducerName = args.ReducerName; + var reducerId = reducerNameToId[reducerName]; + webSocket.Send(new ClientMessage.CallReducer(new CallReducer( - args.ReducerName, + reducerId, IStructuralReadWrite.ToBytes(args), - stats.ReducerRequestTracker.StartTrackingRequest(args.ReducerName), + stats.ReducerRequestTracker.StartTrackingRequest(reducerName), (byte)flags ))); } @@ -950,11 +988,12 @@ T[] LogAndThrow(string error) } var resultTable = result.Tables[0]; - var cacheTable = clientDB.GetTable(resultTable.TableName); + var tableName = tableIdToName[resultTable.TableId]; + var cacheTable = clientDB.GetTable(tableName); if (cacheTable?.ClientTableType != typeof(T)) { - return LogAndThrow($"Mismatched result type, expected {typeof(T)} but got {resultTable.TableName}"); + return LogAndThrow($"Mismatched result type, expected {typeof(T)} but got {tableName}"); } return BsatnRowListIter(resultTable.Rows) diff --git a/tests~/SnapshotTests.cs b/tests~/SnapshotTests.cs index d293c126..12257f25 100644 --- a/tests~/SnapshotTests.cs +++ b/tests~/SnapshotTests.cs @@ -96,13 +96,16 @@ public void Exception(Exception e) } } - private static ServerMessage.IdentityToken SampleId(string identity, string token, string address) => - new(new() + private static IdentityToken SampleId(string identity, string token, string address) => + new() { Identity = Identity.From(Convert.FromBase64String(identity)), Token = token, Address = Address.From(Convert.FromBase64String(address)) ?? throw new InvalidDataException("address") - }); + }; + + private static ServerMessage.AfterConnecting SampleHandshake(string identity, string token, string address, IdsToNames idsToNames) => + new(new(SampleId(identity, token, address), idsToNames)); private static ServerMessage.InitialSubscription SampleSubscriptionUpdate( uint requestId, @@ -123,7 +126,7 @@ private static ServerMessage.TransactionUpdate SampleTransactionUpdate( string callerIdentity, string callerAddress, uint requestId, - string reducerName, + uint reducerId, ulong energyQuantaUsed, ulong hostExecutionDuration, List updates, @@ -141,7 +144,7 @@ private static ServerMessage.TransactionUpdate SampleTransactionUpdate( ReducerCall = new() { RequestId = requestId, - ReducerName = reducerName, + ReducerId = reducerId, Args = args ?? [] }, Status = new UpdateStatus.Committed(new() @@ -152,13 +155,11 @@ private static ServerMessage.TransactionUpdate SampleTransactionUpdate( private static TableUpdate SampleUpdate( uint tableId, - string tableName, List inserts, List deletes ) where T : IStructuralReadWrite => new() { TableId = tableId, - TableName = tableName, NumRows = (ulong)(inserts.Count + deletes.Count), Updates = [new CompressableQueryUpdate.Uncompressed(new QueryUpdate( EncodeRowList(deletes), EncodeRowList(inserts)))] @@ -190,7 +191,7 @@ private static byte[] Encode(in T value) where T : IStructuralReadWrite } private static TableUpdate SampleUserInsert(string identity, string? name, bool online) => - SampleUpdate(4097, "user", [new User + SampleUpdate(4097, [new User { Identity = Identity.From(Convert.FromBase64String(identity)), Name = name, @@ -198,7 +199,7 @@ private static TableUpdate SampleUserInsert(string identity, string? name, bool }], []); private static TableUpdate SampleUserUpdate(string identity, string? oldName, string? newName, bool oldOnline, bool newOnline) => - SampleUpdate(4097, "user", [new User + SampleUpdate(4097, [new User { Identity = Identity.From(Convert.FromBase64String(identity)), Name = newName, @@ -211,7 +212,7 @@ private static TableUpdate SampleUserUpdate(string identity, string? oldName, st }]); private static TableUpdate SampleMessage(string identity, ulong sent, string text) => - SampleUpdate(4098, "message", [new Message + SampleUpdate(4098, [new Message { Sender = Identity.From(Convert.FromBase64String(identity)), Sent = sent, @@ -219,55 +220,61 @@ private static TableUpdate SampleMessage(string identity, ulong sent, string tex }], []); private static ServerMessage[] SampleDump() => [ - SampleId( + SampleHandshake( "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJoZXhfaWRlbnRpdHkiOiI4ZjkwY2M5NGE5OTY4ZGY2ZDI5N2JhYTY2NTAzYTg5M2IxYzM0YjBiMDAyNjhhNTE0ODk4ZGQ5NTRiMGRhMjBiIiwiaWF0IjoxNzE4NDg3NjY4LCJleHAiOm51bGx9.PSn481bLRqtFwIh46nOXDY14X3GKbz8t4K4GmBmz50loU6xzeL7zDdCh1V2cmiQsoGq8Erxg0r_6b6Y5SqKoBA", - "Vd4dFzcEzhLHJ6uNL8VXFg==" + "Vd4dFzcEzhLHJ6uNL8VXFg==", + new IdsToNames( + [42, 50], + ["send_message", "set_name"], + [4097, 4098], + ["user", "message"] + ) ), SampleSubscriptionUpdate( 1, 366, [SampleUserInsert("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, true)] ), SampleTransactionUpdate(0, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 0, "unknown-reducer", 0, 40, [], null + 0, 50, 0, 40, [], null ), SampleTransactionUpdate( 1718487763059031, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 0, "__identity_connected__", 1957615, 66, [SampleUserInsert("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, true)], + 0, 42, 1957615, 66, [SampleUserInsert("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, true)], null ), SampleTransactionUpdate( 1718487768057579, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", - 1, "set_name", 4345615, 70, [SampleUserUpdate("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, "A", true, true)], + 1, 50, 4345615, 70, [SampleUserUpdate("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", null, "A", true, true)], Encode(new SetName { Name = "A" }) ), SampleTransactionUpdate( 1718487775346381, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 1, "send_message", 2779615, 57, [SampleMessage("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", 1718487775346381, "Hello, A!")], + 1, 42, 2779615, 57, [SampleMessage("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", 1718487775346381, "Hello, A!")], Encode(new SendMessage { Text = "Hello, A!" }) ), SampleTransactionUpdate( 1718487777307855, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 2, "set_name", 4268615, 98, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, "B", true, true)], + 2, 50, 4268615, 98, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", null, "B", true, true)], Encode(new SetName { Name = "B" }) ), SampleTransactionUpdate( 1718487783175083, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", - 2, "send_message", 2677615, 40, [SampleMessage("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", 1718487783175083, "Hello, B!")], + 2, 42, 2677615, 40, [SampleMessage("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", 1718487783175083, "Hello, B!")], Encode(new SendMessage { Text = "Hello, B!" }) ), SampleTransactionUpdate( 1718487787645364, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 3, "send_message", 2636615, 28, [SampleMessage("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", 1718487787645364, "Goodbye!")], + 3, 50, 2636615, 28, [SampleMessage("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", 1718487787645364, "Goodbye!")], Encode(new SendMessage { Text = "Goodbye!" }) ), SampleTransactionUpdate( 1718487791901504, "l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "Kwmeu5riP20rvCTNbBipLA==", - 0, "__identity_disconnected__", 3595615, 75, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "B", "B", true, false)], + 0, 42, 3595615, 75, [SampleUserUpdate("l0qzG1GPRtC1mwr+54q98tv0325gozLc6cNzq4vrzqY=", "B", "B", true, false)], null ), SampleTransactionUpdate( 1718487794937841, "j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", "Vd4dFzcEzhLHJ6uNL8VXFg==", - 3, "send_message", 2636615, 34, [SampleMessage("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", 1718487794937841, "Goodbye!")], + 3, 50, 2636615, 34, [SampleMessage("j5DMlKmWjfbSl7qmZQOok7HDSwsAJopRSJjdlUsNogs=", 1718487794937841, "Goodbye!")], Encode(new SendMessage { Text = "Goodbye!" }) ), ];