From 31522d0d12f6fdd5a99177c3aa3db65923a40ec0 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Tue, 20 Apr 2021 08:23:02 -0500 Subject: [PATCH] cleaned up `ReceiveActor` documentation (#4958) * removed confusing and conflicting examples in the `ReceiveActor` documentation * Embedded reference to "how actors restart" YouTube video in supervision docs --- docs/articles/actors/receive-actor-api.md | 73 +++++++---------------- docs/articles/concepts/supervision.md | 2 + 2 files changed, 24 insertions(+), 51 deletions(-) diff --git a/docs/articles/actors/receive-actor-api.md b/docs/articles/actors/receive-actor-api.md index 82b258e9556..553d4194f30 100644 --- a/docs/articles/actors/receive-actor-api.md +++ b/docs/articles/actors/receive-actor-api.md @@ -68,33 +68,28 @@ system.ActorOf(DemoActor.Props(42), "demo"); Another good practice is to declare local messages (messages that are sent in process) within the Actor, which makes it easier to know what messages are generally being sent over the wire vs in process.: ```csharp -public class DemoActor : UntypedActor +public class DemoActor : ReceiveActor { - protected override void OnReceive(object message) + public DemoActor() { - switch (message) + Receive(x => { - case DemoActorLocalMessages.DemoActorLocalMessage1 msg1: - // Handle message here... - break; - case DemoActorLocalMessages.DemoActorLocalMessage2 msg2: - // Handle message here... - break; - default: - break; - } - } + // Handle message here... + }); - class DemoActorLocalMessages + Receive(x => { - public class DemoActorLocalMessage1 - { - } + // Handle message here... + }); + } - public class DemoActorLocalMessage2 - { - } - } + public class DemoActorLocalMessage1 + { + } + + public class DemoActorLocalMessage2 + { + } } ``` @@ -502,32 +497,6 @@ ReceiveAny(o => Console.WriteLine("Received object: " + o); Receive(0 => Console.WriteLine("Received object: " + o); ``` -### Non generic overloads -Receive has non generic overloads: -```csharp -Receive(typeof(string), obj => Console.WriteLine(obj.ToString()) ); -``` -Predicates can go before or after the handler: - -```csharp -Receive(typeof(string), obj => ((string) obj).Length > 5, obj => Console.WriteLine(obj.ToString()) ); -Receive(typeof(string), obj => Console.WriteLine(obj.ToString()), obj => ((string) obj).Length > 5 ); -``` -And the non generic Func - -```csharp -Receive(typeof(string), obj => - { - var s = (string)obj; - if (s.Length > 5) - { - Console.WriteLine("1: " + s); - return true; - } - return false; - }); -``` - ## Reply to messages If you want to have a handle for replying to a message, you can use `Sender`, which gives you an `IActorRef`. You can reply by sending to that `IActorRef` with `Sender.Tell(replyMsg, Self)`. You can also store the `IActorRef` for replying later, or passing on to other actors. If there is no sender (a message was sent without an actor or task context) then the sender defaults to a 'dead-letter' actor ref. @@ -703,7 +672,7 @@ public class HotSwapActor : ReceiveActor }); } - private void Angry(object message) + private void Angry() { Receive(s => s.Equals("foo"), msg => { @@ -716,7 +685,7 @@ public class HotSwapActor : ReceiveActor }); } - private void Happy(object message) + private void Happy() { Receive(s => s.Equals("foo"), msg => { @@ -834,8 +803,10 @@ Use `Kill` like this: victim.Tell(Akka.Actor.Kill.Instance, ActorRefs.NoSender); ``` -## Actors and exceptions -It can happen that while a message is being processed by an actor, that some kind of exception is thrown, e.g. a database exception. +## Actors and Exceptions +An exception can be thrown while a message is being processed by an actor, e.g. a database exception or some other type of runtime exception. + +When this occurs and the exception is not handled via a `try` / `catch` block, the actor's parent will be notified that its child failed with a specific exception type and will use its [supervision strategy](xref:supervision#what-supervision-means) to restart that child. ### What happens to the Message If an exception is thrown while a message is being processed (i.e. taken out of its mailbox and handed over to the current behavior), then this message will be lost. It is important to understand that it is not put back on the mailbox. So if you want to retry processing of a message, you need to deal with it yourself by catching the exception and retry your flow. Make sure that you put a bound on the number of retries since you don't want a system to livelock (so consuming a lot of cpu cycles without making progress). diff --git a/docs/articles/concepts/supervision.md b/docs/articles/concepts/supervision.md index 5e7b7ed72fc..563088c7a3e 100644 --- a/docs/articles/concepts/supervision.md +++ b/docs/articles/concepts/supervision.md @@ -7,6 +7,8 @@ title: Supervision This document outlines the concept behind supervision and what that means for your Akka.NET actors at run-time. + + ## What Supervision Means As described in [Actor Systems](xref:actor-systems) supervision describes a dependency relationship between actors: the supervisor delegates tasks to subordinates and therefore must respond to their failures. When a subordinate detects a failure (i.e. throws an exception), it suspends itself and all its subordinates and sends a message to its supervisor, signaling failure. Depending on the nature of the work to be supervised and the nature of the failure, the supervisor has a choice of the following four options: