From 07ef068ee060d2eb60d0b7d56fc5bdae6d9bfcb7 Mon Sep 17 00:00:00 2001 From: Roger Johansson Date: Thu, 26 Oct 2023 18:09:07 +0200 Subject: [PATCH] handle shutdown (#2070) --- src/Proto.Actor/ActorSystem.cs | 13 ++++++++++++- src/Proto.Actor/Context/ActorContext.cs | 2 +- src/Proto.Actor/Props/Props.cs | 6 ++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Proto.Actor/ActorSystem.cs b/src/Proto.Actor/ActorSystem.cs index 3149ff5ecf..c67a35cec5 100644 --- a/src/Proto.Actor/ActorSystem.cs +++ b/src/Proto.Actor/ActorSystem.cs @@ -26,7 +26,9 @@ public sealed class ActorSystem : IAsyncDisposable { public const string NoHost = "nonhost"; public const string Client = "$client"; +#pragma warning disable CS0618 // Type or member is obsolete private readonly ILogger _logger = Log.CreateLogger(); +#pragma warning restore CS0618 // Type or member is obsolete private string _host = NoHost; private int _port; @@ -41,7 +43,11 @@ public ActorSystem(ActorSystemConfig config) Diagnostics = new DiagnosticsStore(this); ProcessRegistry = new ProcessRegistry(this); Root = NewRoot(); - DeadLetter = new DeadLetterProcess(this).Configure(); + var dl = new DeadLetterProcess(this); + var dlPid = new PID(Address, "$deadletter", dl); + DeadLetterPid = dlPid; + DeadLetter = dl.Configure(); + ProcessRegistry.TryAdd("$deadletter", DeadLetter); Guardians = new Guardians(this); EventStream = new EventStream(this); Metrics = new ProtoMetrics(config.MetricsEnabled); @@ -108,6 +114,11 @@ public ActorSystem(ActorSystemConfig config) /// DeadLetter process that receives all messages that could not be delivered to an actor. /// public Process DeadLetter { get; } + + /// + /// Pid for the DeadLetter process. + /// + public PID DeadLetterPid { get; } /// /// Allows to broadcast messages across the actor system to anyone who explicitly subscribed. diff --git a/src/Proto.Actor/Context/ActorContext.cs b/src/Proto.Actor/Context/ActorContext.cs index 09feaabe23..417c7d391b 100644 --- a/src/Proto.Actor/Context/ActorContext.cs +++ b/src/Proto.Actor/Context/ActorContext.cs @@ -510,7 +510,7 @@ private Task HandleProcessDiagnosticsRequest(ProcessDiagnosticsRequest processDi [MethodImpl(MethodImplOptions.AggressiveInlining)] private Task InternalInvokeUserMessageAsync(object msg) { - if (_state == ContextState.Stopped) + if (_state == ContextState.Stopped || System.Shutdown.IsCancellationRequested) { //already stopped, send message to deadletter process System.DeadLetter.SendUserMessage(Self, msg); diff --git a/src/Proto.Actor/Props/Props.cs b/src/Proto.Actor/Props/Props.cs index dbb311ee8d..78915ece06 100644 --- a/src/Proto.Actor/Props/Props.cs +++ b/src/Proto.Actor/Props/Props.cs @@ -88,6 +88,12 @@ public sealed record Props public static PID DefaultSpawner(ActorSystem system, string name, Props props, PID? parent, Action? callback) { + //if system is shutting down. don't spawn new actors + if (system.Shutdown.IsCancellationRequested) + { + return system.DeadLetterPid; + } + //Ordering is important here //first we create a mailbox and attach it to a process props = system.ConfigureProps(props);