using NetMQ; using Phantom.Utils.Rpc.Message; using Phantom.Utils.Rpc.Sockets; using Phantom.Utils.Tasks; using Serilog; namespace Phantom.Utils.Rpc; public abstract class RpcRuntime<TSocket> where TSocket : ThreadSafeSocket { private readonly TSocket socket; private readonly ILogger runtimeLogger; private readonly MessageReplyTracker replyTracker; private readonly TaskManager taskManager; protected RpcRuntime(RpcSocket<TSocket> socket) { this.socket = socket.Socket; this.runtimeLogger = socket.Config.RuntimeLogger; this.replyTracker = socket.ReplyTracker; this.taskManager = new TaskManager(socket.Config.TaskManagerLogger); } protected async Task Launch() { void RunTask() { try { Run(socket, runtimeLogger, replyTracker, taskManager); } catch (Exception e) { runtimeLogger.Error(e, "Caught exception in RPC thread."); } } try { await Task.Factory.StartNew(RunTask, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); } catch (OperationCanceledException) { // Ignore. } finally { await taskManager.Stop(); await Disconnect(socket, runtimeLogger); socket.Dispose(); runtimeLogger.Information("ZeroMQ runtime stopped."); } } protected abstract void Run(TSocket socket, ILogger logger, MessageReplyTracker replyTracker, TaskManager taskManager); protected virtual Task Disconnect(TSocket socket, ILogger logger) { return Task.CompletedTask; } }