Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
21762b9
Added v1.4.19 placeholder
Aaronontheweb Mar 24, 2021
b545365
close #4860 - use local deploy for TcpManager child actors. (#4862)
erifol Mar 29, 2021
df199f6
Merge pull request #4875 from akkadotnet/dependabot/nuget/Hyperion-0.…
dependabot-preview[bot] Mar 29, 2021
8439b0b
Bump Newtonsoft.Json from 12.0.3 to 13.0.1 (#4866)
dependabot-preview[bot] Mar 29, 2021
71b1838
Fix ClusterMetricsExtensionSpec racy spec
IgorFedchenko Mar 30, 2021
637510b
Merge pull request #4887 from IgorFedchenko/fix-racy-cluster-spec
IgorFedchenko Mar 30, 2021
411a1e0
Clean up Akka.Stream file stream (#4874)
Arkatufus Mar 31, 2021
f5cb089
Supress ActorSelectionMessage with DeadLetterSuppression (migrated fr…
zbynek001 Mar 31, 2021
6748e2a
add CultureInfo for Turkish OS (#4880)
yildizoglu Apr 1, 2021
651c391
Harden FileSink unit tests by using AwaitAssert to wait for file oper…
Arkatufus Apr 1, 2021
d27df3d
Handle CoordinatedShutdown exiting-completed when not joined (#4893)
zbynek001 Apr 1, 2021
5610f95
Persistence fixes (#4892)
zbynek001 Apr 1, 2021
87ab5eb
Added DoNotInherit annotation (#4896)
ismaelhamed Apr 2, 2021
ceefa28
Bump Microsoft.NET.Test.Sdk from 16.9.1 to 16.9.4 (#4894)
dependabot-preview[bot] Apr 3, 2021
88539cc
Add Setup class for NewtonSoftJsonSerializer (#4890)
Arkatufus Apr 3, 2021
dc2c120
fixed up copyright headers (#4898)
Aaronontheweb Apr 5, 2021
716d6f7
Bump Google.Protobuf from 3.15.6 to 3.15.7 (#4900)
dependabot-preview[bot] Apr 5, 2021
4091508
Added PhiAccrualFailureDetector warning logging for slow heartbeats (…
Aaronontheweb Apr 5, 2021
e7b3fb2
replace reflection magic in MNTR with reading of `MultiNodeConfig` pr…
Aaronontheweb Apr 6, 2021
d3197dd
fixed SBR logging error that blew up StandardOutLogger (#4909)
Aaronontheweb Apr 6, 2021
ec3fc61
added timestamp to node failures in MNTR (#4911)
Aaronontheweb Apr 6, 2021
85ef5d8
cleaned up the SpecPass / SpecFail messages (#4912)
Aaronontheweb Apr 6, 2021
a4b611d
reduce allocations inside PhiAccrualFailureDetector (#4913)
Aaronontheweb Apr 7, 2021
bb633b2
Bump Microsoft.Data.SQLite from 5.0.4 to 5.0.5 (#4914)
dependabot-preview[bot] Apr 7, 2021
9e6a94d
[MNTR] Add include and exclude test filter feature (#4916)
Arkatufus Apr 7, 2021
7f200f5
cleaned up RemoteWatcher (#4917)
Aaronontheweb Apr 7, 2021
a800f8d
Fixed System.ArgumentNullException in Interspase operation on empty s…
genietonic Apr 8, 2021
5cc93ee
Rewrite the AkkaDiFixture so that it does not need to start a HostBui…
Danthar Apr 8, 2021
1d144d7
Fix case where PersistenceMessageSerializer.FromBinary got a null for…
Arkatufus Apr 9, 2021
56cae11
Bump Google.Protobuf from 3.15.7 to 3.15.8 (#4927)
dependabot-preview[bot] Apr 9, 2021
ee08dba
close #4096 - documented how to terminate remembered entities (#4928)
Aaronontheweb Apr 9, 2021
da88578
Add CLI switches to show help and version number (#4925)
Arkatufus Apr 10, 2021
950f824
cleaned up protobuf CLI and definitions (#4930)
Aaronontheweb Apr 11, 2021
ef383bc
Fix MNTK specs for DData: DurablePruningSpec (#4933)
Arkatufus Apr 12, 2021
fc5b043
Powershell splits CLI arguments on "." before passing them into appli…
Arkatufus Apr 12, 2021
97628d4
porting Cluster heartbeat timings, hardened Akka.Cluster serializatio…
Aaronontheweb Apr 13, 2021
56a787a
Bump Hyperion from 0.9.17 to 0.10.0 (#4935)
dependabot-preview[bot] Apr 14, 2021
87cc645
Add spec for handling delegates in DI (#4922)
Arkatufus Apr 14, 2021
c87b627
Bump FsCheck from 2.15.1 to 2.15.2 (#4939)
dependabot-preview[bot] Apr 16, 2021
3ac3ee8
ClusterStressSpec and Cluster Failure Detector Cleanup (#4940)
Aaronontheweb Apr 16, 2021
5e94772
Bump FsCheck.Xunit from 2.15.1 to 2.15.2 (#4938)
dependabot-preview[bot] Apr 16, 2021
e0f8604
cleanup `AKKA_CLUSTER_ASSERT` environment variable (#4942)
Aaronontheweb Apr 17, 2021
ac07a0f
harden Akka.DependencyInjection.Tests (#4945)
Aaronontheweb Apr 17, 2021
234188e
HeartbeatNodeRing performance (#4943)
Aaronontheweb Apr 18, 2021
65e5a22
modified PingPong / RemotePingPong benchmarks to display threadcount …
Aaronontheweb Apr 18, 2021
19f1580
Configure duration for applying `MemberStatus.WeaklyUp` to joining n…
Aaronontheweb Apr 19, 2021
1800e38
restored Akka.Cluster model-based FsCheck specs (#4949)
Aaronontheweb Apr 19, 2021
45bbd3b
added `VectorClock` benchmark (#4950)
Aaronontheweb Apr 19, 2021
1f81842
Performance optimize `VectorClock` (#4952)
Aaronontheweb Apr 19, 2021
2de428b
harden RestartFirstSeedNodeSpec (#4954)
Aaronontheweb Apr 19, 2021
aed2cbc
Turned `HeatbeatNodeRing` into `struct` (#4944)
Aaronontheweb Apr 19, 2021
3c2f098
Add generalized crossplatform support for Hyperion serializer. (#4878)
Arkatufus Apr 19, 2021
31522d0
cleaned up `ReceiveActor` documentation (#4958)
Aaronontheweb Apr 20, 2021
696710e
updated website footer to read 2021 (#4959)
Aaronontheweb Apr 20, 2021
36585d8
added indicator for `ClusterResultsAggregator` in `StressSpec` logs (…
Aaronontheweb Apr 20, 2021
8d03165
Bump Hyperion from 0.10.0 to 0.10.1 (#4957)
dependabot-preview[bot] Apr 20, 2021
3f232d8
Perf optimize `ActorSelection` (#4962)
Aaronontheweb Apr 20, 2021
a0da8cd
`Reachability` performance optimziation (#4955)
Aaronontheweb Apr 20, 2021
71a2a29
Fix `SpawnActor` benchmark (#4966)
Aaronontheweb Apr 20, 2021
d06eb36
fixed N-1 error inside `Mailbox` (#4964)
Aaronontheweb Apr 21, 2021
c4c6443
Clean up bad outbound ACKs in Akka.Remote (#4963)
Aaronontheweb Apr 21, 2021
676f566
UnfoldResourceSource closing twice on failure (#4969)
ismaelhamed Apr 21, 2021
8c8c009
Add retry pattern with delay calculation support (#4895)
ismaelhamed Apr 21, 2021
953fc0f
simplified the environment variable name for StressSpec (#4972)
Aaronontheweb Apr 21, 2021
5251f36
Refactored `Gossip` into `MembershipState` (#4968)
Aaronontheweb Apr 21, 2021
442f8eb
Fix serialization verification problem with Akka.IO messages (#4974)
Arkatufus Apr 23, 2021
321d0e4
ORDictionary with POCO value missing items, add MultiNode spec (#4910)
Arkatufus Apr 23, 2021
d178b63
clean up seed node process (#4975)
Aaronontheweb Apr 23, 2021
101f5a2
fixed racy ActorModelSpec (#4976)
Aaronontheweb Apr 23, 2021
a1fa221
Update PluginSpec so that it can accept ActorSystem and ActorSystemSe…
Arkatufus Apr 26, 2021
e58d36a
Removed inaccurate warning from Cluster Singleton docs (#4980)
Aaronontheweb Apr 27, 2021
bdfc893
Introduce `ChannelExecutor` (#4882)
Aaronontheweb Apr 28, 2021
82d7909
Upgrade to GitHub-native Dependabot (#4984)
dependabot-preview[bot] Apr 28, 2021
a3feeef
added v1.4.19 release notes (#4985)
Aaronontheweb Apr 28, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
version: 2
updates:
- package-ecosystem: nuget
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
ignore:
- dependency-name: NUnit
versions:
- 3.13.0
- 3.13.1
- dependency-name: Google.Protobuf
versions:
- 3.15.0
- 3.15.1
- 3.15.4
- dependency-name: FsCheck.Xunit
versions:
- 2.14.5
- 2.15.0
- dependency-name: FsCheck
versions:
- 2.14.5
- dependency-name: FluentAssertions
versions:
- 5.9.0
121 changes: 121 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,124 @@
#### 1.4.19 April 28 2021 ####
**Maintenance Release for Akka.NET 1.4**

Akka.NET v1.4.19 is a _substantial_ release that includes a number of critical Akka.Cluster fixes, baseline Akka.NET performance improvements, and entirely new dispatcher that has shown to improve performance when used across all of the major actor groups that run both inside the `/user` hierarchy and the `/system` actor hierarchy as well.

**Akka.Cluster Improvements**
One of the most demanding issues of the v1.4.19 release was "[Akka.Cluster: quarantining / reachability changes appear to be extremely sensitive](https://github.com/akkadotnet/akka.net/issues/4849)" - and this is because debugging this issue touched so many different parts of Akka.Cluster.

We ultimately solved the problem - it is now quite feasible to rapidly scale an Akka.NET cluster from ~10 nodes to 50+ nodes without having a huge number of quarantines, accidentally downed nodes, and so on.

Here's the full set of fixes that went into resolving this issue:

* [Added `PhiAccrualFailureDetector` warning logging for slow heartbeats](https://github.com/akkadotnet/akka.net/pull/4897)
* [measure Akka.Cluster heartbeat timings, hardened Akka.Cluster serialization](https://github.com/akkadotnet/akka.net/pull/4934)
* [`ClusterStressSpec` and Cluster Failure Detector Cleanup](https://github.com/akkadotnet/akka.net/pull/4940)
* [Akka.Cluster: improve `HeartbeatNodeRing` performance](https://github.com/akkadotnet/akka.net/pull/4943)
* [Akka.Cluster: Turned `HeatbeatNodeRing` into `struct`](https://github.com/akkadotnet/akka.net/pull/4944)
* [Akka.Cluster: Configure duration for applying `MemberStatus.WeaklyUp` to joining nodes](https://github.com/akkadotnet/akka.net/pull/4946)
* [Akka.Cluster: Performance optimize `VectorClock`](https://github.com/akkadotnet/akka.net/pull/4952)
* [Akka.Cluster: Refactored `Gossip` into `MembershipState`](https://github.com/akkadotnet/akka.net/pull/4968)
* [Akka.Remote: Clean up bad outbound ACKs in Akka.Remote](https://github.com/akkadotnet/akka.net/pull/4963)

Akka.Cluster is now much more robust, faster, and capable of scaling up and down much more efficiently than in previous releases.

**`ChannelExecutor` and Akka Performance Improvements**
In addition to improving Akka.Cluster, we also made substantial improvements to constructs found inside Akka.NET core itself:

* [Perf optimize `ActorSelection`](https://github.com/akkadotnet/akka.net/pull/4962) - 20% throughput improvement, 25% memory consumption improvement
* [fixed N-1 error inside `Mailbox`](https://github.com/akkadotnet/akka.net/pull/4964)
* [Introduce `ChannelExecutor`](https://github.com/akkadotnet/akka.net/pull/4882)

In Akka.NET v1.4.19 we introduce an opt-in feature, the `ChannelExecutor` - a new dispatcher type that re-uses the same configuration as a `ForkJoinDispatcher` but runs entirely on top of the .NET `ThreadPool` and is able to take advantage of dynamic thread pool scaling to size / resize workloads on the fly.

In order to get the most use out of the `ChannelExecutor`, the default actor dispatcher, the internal dispatcher, and the Akka.Remote dispatchers all need to run on it - and you can see the latest configuration settings and guidance for that here in our documentation: https://getakka.net/articles/actors/dispatchers.html#channelexecutor

But a copy of today's configuration is included below - you can enable this feature inside your Akka.NET applications via the following HOCON:

```
akka.actor.default-dispatcher = {
executor = channel-executor
fork-join-executor { #channelexecutor will re-use these settings
parallelism-min = 2
parallelism-factor = 1
parallelism-max = 64
}
}

akka.actor.internal-dispatcher = {
executor = channel-executor
throughput = 5
fork-join-executor {
parallelism-min = 4
parallelism-factor = 1.0
parallelism-max = 64
}
}

akka.remote.default-remote-dispatcher {
type = Dispatcher
executor = channel-executor
fork-join-executor {
parallelism-min = 2
parallelism-factor = 0.5
parallelism-max = 16
}
}

akka.remote.backoff-remote-dispatcher {
executor = channel-executor
fork-join-executor {
parallelism-min = 2
parallelism-max = 2
}
}
```

**We are looking for feedback on how well the `ChannelExecutor` works in real world applications here: https://github.com/akkadotnet/akka.net/discussions/4983**

**Hyperion v0.10 and Improvements**
We also released [Hyperion v0.10.0](https://github.com/akkadotnet/Hyperion/releases/tag/0.10.0) and [v0.10.1](https://github.com/akkadotnet/Hyperion/releases/tag/0.10.1) as part of the Akka.NET v1.4.19 sprint, and this includes some useful changes for Akka.NET users who are trying to build cross-platform (.NET Framework + .NET Core / .NET 5) applications and need to handle all of the idiosyncrasies those platforms introduced by changing the default namespaces on primitive types such as `string` and `int`.

We have also introduced a [new `Setup` type](https://getakka.net/articles/concepts/configuration.html#programmatic-configuration-with-setup) designed to make it easy to resolve some of these "cross platform" serialization concerns programmatically when configuring Hyperion for use inside Akka.NET:

```csharp
#if NETFRAMEWORK
var hyperionSetup = HyperionSerializerSetup.Empty
.WithPackageNameOverrides(new Func<string, string>[]
{
str => str.Contains("System.Private.CoreLib,%core%")
? str.Replace("System.Private.CoreLib,%core%", "mscorlib,%core%") : str
}
#elif NETCOREAPP
var hyperionSetup = HyperionSerializerSetup.Empty
.WithPackageNameOverrides(new Func<string, string>[]
{
str => str.Contains("mscorlib,%core%")
? str.Replace("mscorlib,%core%", "System.Private.CoreLib,%core%") : str
}
#endif

var bootstrap = BootstrapSetup.Create().And(hyperionSetup);
var system = ActorSystem.Create("actorSystem", bootstrap);
```

See the full documentation for this feature here: https://getakka.net/articles/networking/serialization.html#cross-platform-serialization-compatibility-in-hyperion

To see the [full set of fixes in Akka.NET v1.4.19, please see the milestone on Github](https://github.com/akkadotnet/akka.net/milestone/49).

| COMMITS | LOC+ | LOC- | AUTHOR |
| --- | --- | --- | --- |
| 38 | 6092 | 4422 | Aaron Stannard |
| 13 | 2231 | 596 | Gregorius Soedharmo |
| 10 | 15 | 14 | dependabot-preview[bot] |
| 3 | 512 | 306 | zbynek001 |
| 3 | 417 | 1 | Ismael Hamed |
| 1 | 5 | 5 | Erik Følstad |
| 1 | 5 | 19 | Arjen Smits |
| 1 | 27 | 1 | Anton V. Ilyin |
| 1 | 21 | 33 | Igor |
| 1 | 1 | 1 | Cagatay YILDIZOGLU |

#### 1.4.18 March 23 2021 ####
**Maintenance Release for Akka.NET 1.4**

Expand Down
3 changes: 2 additions & 1 deletion build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ Target "MultiNodeTests" (fun _ ->

Target "MultiNodeTestsNetCore" (fun _ ->
if not skipBuild.Value then
setEnvironVar "AKKA_CLUSTER_ASSERT" "on" // needed to enable assert invariants for Akka.Cluster
let multiNodeTestPath = findToolInSubPath "Akka.MultiNodeTestRunner.dll" (currentDirectory @@ "src" @@ "core" @@ "Akka.MultiNodeTestRunner" @@ "bin" @@ "Release" @@ testNetCoreVersion @@ "win10-x64" @@ "publish")

let projects =
Expand Down Expand Up @@ -388,6 +389,7 @@ Target "MultiNodeTestsNetCore" (fun _ ->
)
Target "MultiNodeTestsNet" (fun _ ->
if not skipBuild.Value then
setEnvironVar "AKKA_CLUSTER_ASSERT" "on" // needed to enable assert invariants for Akka.Cluster
let multiNodeTestPath = findToolInSubPath "Akka.MultiNodeTestRunner.dll" (currentDirectory @@ "src" @@ "core" @@ "Akka.MultiNodeTestRunner" @@ "bin" @@ "Release" @@ testNetVersion @@ "win10-x64" @@ "publish")

let projects =
Expand Down Expand Up @@ -626,7 +628,6 @@ Target "Protobuf" <| fun _ ->
|> append (sprintf "-I=%s" (__SOURCE_DIRECTORY__ @@ "/src/protobuf/common") )
|> append (sprintf "--csharp_out=internal_access:%s" (__SOURCE_DIRECTORY__ @@ destinationPath))
|> append "--csharp_opt=file_extension=.g.cs"
|> append "--experimental_allow_proto3_optional"
|> append (__SOURCE_DIRECTORY__ @@ "/src/protobuf" @@ protoName)
|> toText

Expand Down
58 changes: 58 additions & 0 deletions docs/articles/actors/dispatchers.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Some dispatcher configurations are available out-of-the-box for convenience. You
* **task-dispatcher** - A configuration that uses the [TaskDispatcher](#taskdispatcher).
* **default-fork-join-dispatcher** - A configuration that uses the [ForkJoinDispatcher](#forkjoindispatcher).
* **synchronized-dispatcher** - A configuration that uses the [SynchronizedDispatcher](#synchronizeddispatcher).
* **channel-executor** - new as of v1.4.19, the [`ChannelExecutor`](#channelexecutor) is used to run on top of the .NET `ThreadPool` and allow Akka.NET to dynamically scale thread usage up and down with demand in exchange for better CPU and throughput performance.

## Built-in Dispatchers

Expand Down Expand Up @@ -165,6 +166,63 @@ private void Form1_Load(object sender, System.EventArgs e)
}
```

### `ChannelExecutor`
In Akka.NET v1.4.19 we will be introducing an opt-in feature, the `ChannelExecutor` - a new dispatcher type that re-uses the same configuration as a `ForkJoinDispatcher` but runs entirely on top of the .NET `ThreadPool` and is able to take advantage of dynamic thread pool scaling to size / resize workloads on the fly.

During its initial development and benchmarks, we observed the following:

1. The `ChannelExecutor` tremendously reduced idle CPU and max busy CPU even during peak message throughput, primarily as a result of dynamically shrinking the total `ThreadPool` to only the necessary size. This resolves one of the largest complaints large users of Akka.NET have today. However, **in order for this setting to be effective `ThreadPool.SetMin(0,0)` must also be set**. We are considering doing this inside the `ActorSystem.Create` method, those settings don't work for you you can easily override them by simply calling `ThreadPool.SetMin(yourValue, yourValue)` again after `ActorSystem.Create` has exited.
2. The `ChannelExecutor` actually beat the `ForkJoinDispatcher` and others on performance even in environments like Docker and bare metal on Windows.

> [!NOTE]
> We are in the process of gathering data from users on how well `ChannelExecutor` performs in the real world. If you are interested in trying out the `ChannelExecutor`, please read the directions in this document and then comment on [the "Akka.NET v1.4.19: ChannelExecutor performance data" discussion thread](https://github.com/akkadotnet/akka.net/discussions/4983).

The `ChannelExectuor` re-uses the same threading settings as the `ForkJoinExecutor` to determine its effective upper and lower parallelism limits, and you can configure the `ChannelExecutor` to run inside your `ActorSystem` via the following HOCON configuration:

```
akka.actor.default-dispatcher = {
executor = channel-executor
fork-join-executor { #channelexecutor will re-use these settings
parallelism-min = 2
parallelism-factor = 1
parallelism-max = 64
}
}

akka.actor.internal-dispatcher = {
executor = channel-executor
throughput = 5
fork-join-executor {
parallelism-min = 4
parallelism-factor = 1.0
parallelism-max = 64
}
}

akka.remote.default-remote-dispatcher {
type = Dispatcher
executor = channel-executor
fork-join-executor {
parallelism-min = 2
parallelism-factor = 0.5
parallelism-max = 16
}
}

akka.remote.backoff-remote-dispatcher {
executor = channel-executor
fork-join-executor {
parallelism-min = 2
parallelism-max = 2
}
}
```

This will enable the `ChannelExecutor` to run everywhere and all Akka.NET loads, with the exception of anything you manually allocate onto a `ForkJoinDispatcher` or `PinnedDispatcher`, will be managed by the `ThreadPool`.

> [!IMPORTANT]
> As of Akka.NET v1.4.19, we call `ThreadPool.SetMinThreads(0,0)` inside the `ActorSystem.Create` method as we've found that the default `ThreadPool` minimum values have a negative impact on performance. However, if this causes undesireable side effects for you inside your application you can always override those settings by calling `ThreadPool.SetMinThreads(yourValue, yourValue)` again after you've created your `ActorSystem`.

#### Common Dispatcher Configuration

The following configuration keys are available for any dispatcher configuration:
Expand Down
73 changes: 22 additions & 51 deletions docs/articles/actors/receive-actor-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<DemoActor.DemoActorLocalMessage1>(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<DemoActor.DemoActorLocalMessage2>(x =>
{
public class DemoActorLocalMessage1
{
}
// Handle message here...
});
}

public class DemoActorLocalMessage2
{
}
}
public class DemoActorLocalMessage1
{
}

public class DemoActorLocalMessage2
{
}
}
```

Expand Down Expand Up @@ -502,32 +497,6 @@ ReceiveAny(o => Console.WriteLine("Received object: " + o);
Receive<object>(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.

Expand Down Expand Up @@ -703,7 +672,7 @@ public class HotSwapActor : ReceiveActor
});
}

private void Angry(object message)
private void Angry()
{
Receive<string>(s => s.Equals("foo"), msg =>
{
Expand All @@ -716,7 +685,7 @@ public class HotSwapActor : ReceiveActor
});
}

private void Happy(object message)
private void Happy()
{
Receive<string>(s => s.Equals("foo"), msg =>
{
Expand Down Expand Up @@ -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).
Expand Down
Loading