Skip to content

Commit

Permalink
v1.4.19 Akka.NET Release (#4987)
Browse files Browse the repository at this point in the history
* Added v1.4.19 placeholder

* close #4860 - use local deploy for TcpManager child actors. (#4862)

* close #4860 - use local deploy for TcpManager child actors.

* Use local deploy for TcpIncomingConnection.

* Use local deploy for Udp actors.

Co-authored-by: Erik Folstad <erikmafo@gmail.com>
Co-authored-by: Aaron Stannard <aaron@petabridge.com>

* Merge pull request #4875 from akkadotnet/dependabot/nuget/Hyperion-0.9.17

Bump Hyperion from 0.9.16 to 0.9.17

* Bump Newtonsoft.Json from 12.0.3 to 13.0.1 (#4866)

Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 12.0.3 to 13.0.1.
- [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases)
- [Commits](JamesNK/Newtonsoft.Json@12.0.3...13.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* Fix ClusterMetricsExtensionSpec racy spec

* Clean up Akka.Stream file stream (#4874)

* Make sure that FileSubscriber shuts down cleanly when it dies

* Make sure that file all sink spec release the file handle if it fails

* Supress ActorSelectionMessage with DeadLetterSuppression (migrated from akka/akka#28341) (#4889)

* for example the Cluster InitJoin message is marked with DeadLetterSuppression
  but was anyway logged because sent with actorSelection
* for other WrappedMessage than ActorSelectionMessage we shouldn't unwrap and publish
  the inner in SuppressedDeadLetter because that might loose some information
* therefore those are silenced in the DeadLetterListener instead

Better deadLetter logging of wrapped messages (migrated from akka/akka#28253)

Logging of UnhandledMessage (migrated from akka/akka#28414)
* make use of the existing logging of dead letter
  also for UnhandledMessage

Add Dropped to Akka.Actor (migrated partially from akka/akka#27160)
Log Dropped from DeadLetterListener

* add CultureInfo for Turkish OS (#4880)

* add CultureInfo for Turkish OS

added English CultureInfo to fix ToUpper function causes error on Turkish OS. "warning"->"WARNİNG"

* fix LogLevel TR char error

Co-authored-by: Aaron Stannard <aaron@petabridge.com>

* Harden FileSink unit tests by using AwaitAssert to wait for file operations to complete (#4891)

* Harden FileSink unit tests by using AwaitAssert to wait for file operations to complete

* Use AwaitResult to improve readability

Co-authored-by: Aaron Stannard <aaron@petabridge.com>

* Handle CoordinatedShutdown exiting-completed when not joined (#4893)

* assertion failed: Nodes not part of cluster have marked the Gossip as seen
* trying to mark the Gossip as seen before it has joined, which may happen
  if CoordinatedShutdown is running before the node has joined

migrated from akka/akka#26835

* Persistence fixes (#4892)

* snapshot RecoveryTick ignored, part of akka/akka#20753

* lastSequenceNr should reflect the snapshot sequence and not start with 0 when journal is empty. Migrated from akka/akka#27496

* Enforce valid seqnr for deletes, migrated from akka/akka#25488

* api approval

* Added DoNotInherit annotation (#4896)

* Bump Microsoft.NET.Test.Sdk from 16.9.1 to 16.9.4 (#4894)

* Add Setup class for NewtonSoftJsonSerializer (#4890)

* Add Setup class for NewtonSoftJsonSerializer

* Use Setup as a settings modifier instead of a settings factory

* Update spec

* Update API Approval list

* Unit test can inject null ActorSystem into the serializer causing the Setup system to throw a NRE

* Add documentation

* fixed up copyright headers (#4898)

* Bump Google.Protobuf from 3.15.6 to 3.15.7 (#4900)

Bumps [Google.Protobuf](https://github.com/protocolbuffers/protobuf) from 3.15.6 to 3.15.7.
- [Release notes](https://github.com/protocolbuffers/protobuf/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf/blob/master/generate_changelog.py)
- [Commits](protocolbuffers/protobuf@v3.15.6...v3.15.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* Added PhiAccrualFailureDetector warning logging for slow heartbeats (#4897)

Ported from akka/akka#17389 and akka/akka#24701

* replace reflection magic in MNTR with reading of `MultiNodeConfig` properties (#4902)

* close #4901 - replace reflection magic in MNTR with reading of MultiNodeConfig properties

* fixed outdated DiscoverySpec

* fixed SBR logging error that blew up StandardOutLogger (#4909)

This format error would cause the StandardOutLogger to throw a `FormatException` internally

* added timestamp to node failures in MNTR (#4911)

* cleaned up the SpecPass / SpecFail messages (#4912)

* reduce allocations inside PhiAccrualFailureDetector (#4913)

made `HeartbeatHistory` into a `readonly struct` and cleaned up some other old LINQ calls inside the data structure

* Bump Microsoft.Data.SQLite from 5.0.4 to 5.0.5 (#4914)

* [MNTR] Add include and exclude test filter feature (#4916)

* Add -Dmultinode.include and -Dmultinode.exclude filter feature

* Add documentation

* Fix typos and makes sentences more readable

* Make the sample command line wrap instead of running off the screen

* Change include and exclude filtering by method name instead (requested)

* cleaned up RemoteWatcher (#4917)

* Fixed System.ArgumentNullException in Interspase operation on empty stream finish. (#4918)

* Rewrite the AkkaDiFixture so that it does not need to start a HostBuilder (#4920)

* Fix case where PersistenceMessageSerializer.FromBinary got a null for its type parameter (#4923)

* Bump Google.Protobuf from 3.15.7 to 3.15.8 (#4927)

Bumps [Google.Protobuf](https://github.com/protocolbuffers/protobuf) from 3.15.7 to 3.15.8.
- [Release notes](https://github.com/protocolbuffers/protobuf/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf/blob/master/generate_changelog.py)
- [Commits](protocolbuffers/protobuf@v3.15.7...v3.15.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* close #4096 - documented how to terminate remembered entities (#4928)

Updated the Akka.Cluster.Sharding documentation to explain how to terminate remembered-entities.

* Add CLI switches to show help and version number (#4925)

* cleaned up protobuf CLI and definitions (#4930)

* cleaned up protobuf CLI and definitions

- Remove all `optional` fields (not allowed in Protobuf3, as all fields are optional by default unless specifically defined as `required`)
- Removed `--experimental_allow_proto3_optional` call from `protoc` compiler as it's no longer supported / needed
- Doesn't have any impact on existing wire formats, especially for `ClusterMessages.proto` which is where I removed all of the `optional` commands

* fixed compilation error caused by change in generated `AppVersion` output

* Fix MNTK specs for DData: DurablePruningSpec (#4933)

* Powershell splits CLI arguments on "." before passing them into applications (#4924)

* porting Cluster heartbeat timings, hardened Akka.Cluster serialization (#4934)

* porting Cluster heartbeat timings, hardened Akka.Cluster serialization

port akka/akka#27281
port akka/akka#25183
port akka/akka#24625

* increased ClusterLogSpec join timespan

Increased the `TimeSpan` here to 10 seconds in order to prevent this spec from failing racily, since even an Akka.Cluster self-join can take more than the default 3 seconds due to some of the timings involved in node startup et al.

* Bump Hyperion from 0.9.17 to 0.10.0 (#4935)

Bumps [Hyperion](https://github.com/akkadotnet/Hyperion) from 0.9.17 to 0.10.0.
- [Release notes](https://github.com/akkadotnet/Hyperion/releases)
- [Changelog](https://github.com/akkadotnet/Hyperion/blob/dev/RELEASE_NOTES.md)
- [Commits](akkadotnet/Hyperion@0.9.17...0.10.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* Add spec for handling delegates in DI (#4922)

* Add spec for handling delegates in DI

* Make sure spec exits cleanly by terminating the actor system.

* Add spec where singleton delegate is called from another actor

* Fix racy test

Co-authored-by: Aaron Stannard <aaron@petabridge.com>

* Bump FsCheck from 2.15.1 to 2.15.2 (#4939)

* ClusterStressSpec and Cluster Failure Detector Cleanup (#4940)

* implementation of Akka.Cluster.Tests.MultiNode.StressSpec

* made MuteLog overrideable in Akka.Cluster.Testkit

* if Roles is empty, then don't run the thunk on any nodes

Changed this to make it consistent with the JVM

* made it possible to actually enable Cluster.AssertInvariants via environment variable

* added assert invariants to build script

cleaned up gossip class to assert more invariants

* ReSharper'd Reachability.cs

* cleaned up immutability and CAS issues inside DefaultFailureDetectorRegistry

added bugfix from akka/akka#23595

* Bump FsCheck.Xunit from 2.15.1 to 2.15.2 (#4938)

Bumps [FsCheck.Xunit](https://github.com/fsharp/FsCheck) from 2.15.1 to 2.15.2.
- [Release notes](https://github.com/fsharp/FsCheck/releases)
- [Changelog](https://github.com/fscheck/FsCheck/blob/master/FsCheck%20Release%20Notes.md)
- [Commits](fscheck/FsCheck@2.15.1...2.15.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* cleanup `AKKA_CLUSTER_ASSERT` environment variable (#4942)

Per some of the suggestions on #4940 PR review

* harden Akka.DependencyInjection.Tests (#4945)

Added some `AwaitAssert` calls to check for disposed dependencies - these calls can be racy due to background actor thread calling `Dipose` after foreground test thread checks the `Disposed` property.

* HeartbeatNodeRing performance (#4943)

* added benchmark for HeartbeatNodeRing performance

* switched to local function

No perf change

* approve Akka.Benchmarks friend assembly for Akka.Cluster

* remove HeartbeatNodeRing.NodeRing() allocation and make field immutable

* made it so Akka.Util.Internal.ArrayExtensions.From no longer allocates (much)

* added some descriptive comments on HeartbeatNodeRing.Receivers

* Replaced `Lazy<T>` with `Option<T>` and a similar lazy initialization check

 Improved throughput by ~10% on larger collections and further reduced memory allocation.

* changed return types to `IImmutableSet`

Did this in order to reduce allocations from constantly converting back and forth from `ImmutableSortedSet<T>` and `ImmutableHashSet<T>` - that way we can just use whatever the underlying collection type is.

* added ReachabilityBenchmarks

* modified PingPong / RemotePingPong benchmarks to display threadcount (#4947)

Using this to gauge the impact certain dispatcher changes have on the total number of active threads per-process

* Configure duration for applying `MemberStatus.WeaklyUp`  to joining nodes (#4946)

* Configure duration for applying `MemberStatus.WeaklyUp`  to joining nodes

port of akka/akka#29665

* fixed validation check for TimeSpan duration passed in via HOCON

* harden ClusterLogSpecs

* restored Akka.Cluster model-based FsCheck specs (#4949)

* added `VectorClock` benchmark (#4950)

* added VectorClock benchmark

* fixed broken benchmark comparisons

* Performance optimize `VectorClock` (#4952)

* Performance optimize `VectorClock`

* don't cache MD5, but dispose of it

* guarantee disposal of iterators during VectorClock.Compare

* switch to local function for `VectorClock.CompareNext`

* fixed a comparison bug in how versions where compared

* minor cleanup

* replace `KeyValuePair<TKey,TValue>` with `ValueTuple<TKey,TValue>`

Reduced allocations by 90%, decreased execution time from 100ms to ~40ms

* harden RestartFirstSeedNodeSpec (#4954)

* harden RestartFirstSeedNodeSpec

* validate that we have complete seed node list prior to test

* Turned `HeatbeatNodeRing` into `struct` (#4944)

* added benchmark for HeartbeatNodeRing performance

* switched to local function

No perf change

* approve Akka.Benchmarks friend assembly for Akka.Cluster

* remove HeartbeatNodeRing.NodeRing() allocation and make field immutable

* made it so Akka.Util.Internal.ArrayExtensions.From no longer allocates (much)

* added some descriptive comments on HeartbeatNodeRing.Receivers

* Replaced `Lazy<T>` with `Option<T>` and a similar lazy initialization check

 Improved throughput by ~10% on larger collections and further reduced memory allocation.

* changed return types to `IImmutableSet`

Did this in order to reduce allocations from constantly converting back and forth from `ImmutableSortedSet<T>` and `ImmutableHashSet<T>` - that way we can just use whatever the underlying collection type is.

* converted `HeartbeatNodeRing` into a `struct`

improved performance some, but I don't want to lump it in with other changes just in case

* Add generalized crossplatform support for Hyperion serializer. (#4878)

* Add the groundwork for generalized crossplatform support.

* Update Hyperion to 0.10.0

* Convert adapter class to lambda object

* Add HyperionSerializerSetup setup class

* Add unit test spec

* Improve specs, add comments

* Add documentation

* Add copyright header.

* Change readonly fields to readonly properties.

* 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

* updated website footer to read 2021 (#4959)

* added indicator for `ClusterResultsAggregator` in `StressSpec` logs (#4960)

Did this to make it easier to search for output logs produced during each phase of the `StressSpec`

* Bump Hyperion from 0.10.0 to 0.10.1 (#4957)

* Bump Hyperion from 0.10.0 to 0.10.1

Bumps [Hyperion](https://github.com/akkadotnet/Hyperion) from 0.10.0 to 0.10.1.
- [Release notes](https://github.com/akkadotnet/Hyperion/releases)
- [Changelog](https://github.com/akkadotnet/Hyperion/blob/dev/RELEASE_NOTES.md)
- [Commits](akkadotnet/Hyperion@0.10.0...0.10.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

* Fix dependabot Hyperion issue (#4961)

* Update Akka.Remote.Tests.csproj to use common.props

* Update HyperionSerializer to reflect recent hyperion changes

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: Gregorius Soedharmo <arkatufus@yahoo.com>

* Perf optimize `ActorSelection` (#4962)

* added memory metrics to `ActorSelection` benchmarks

* added ActorSelection benchmark

* ramped up the iteration counts

* validate that double wildcard can't be used outside of leaf node

* improve allocations on create

* minor cleanup

* create emptyRef only when needed via local function

* made `Iterator` into `struct`

* approved public API changes

* `Reachability` performance optimziation (#4955)

* reduced iteration count to speed up benchmarks

* optimize some System.Collections.Immutable invocations to allocate less

* cleanup dictionary construction

* fixed multiple enumeration bug in `Reachability`

* Fix `SpawnActor` benchmark (#4966)

* cleaned up SpawnActorBenchmarks

* cleaned up SpawnActor benchmarks

* fixed N-1 error inside `Mailbox` (#4964)

This error has no impact on extremely busy actors, but for actors who have to process small bursts of messages this can make the difference between getting everything done in one dispatch vs. doing it in two.

* Clean up bad outbound ACKs in Akka.Remote (#4963)

port of akka/akka#20093

Might be responsible for some quarantines in Akka.Cluster / Akka.Remote when nodes are restarting on identical addresses.

* UnfoldResourceSource closing twice on failure (#4969)

* Added test cases where close would be called twice

* Bugfix UnfoldResource closed resource twice on failure

* Add retry pattern with delay calculation support (#4895)

Co-authored-by: Aaron Stannard <aaron@petabridge.com>

* simplified the environment variable name for StressSpec (#4972)

* Refactored `Gossip` into `MembershipState` (#4968)

* refactor Gossip class into `MembershipState`

port of akka/akka#23291

* completed `MembershipState` port

* fixed some downed observers calls

* forgot to copy gossip upon `Welcome` from Leader

* forgot to copy `MembershipState` while calling `UpdateLatestGossip`

* refactored all DOWN-ing logic to live inside `Gossip` class

* added some additional methods onto `MembershipState`

* fixed ValidNodeForGossip bug

* fixed equality check for Reachability

 should be quality by reference, not by value

Co-authored-by: Gregorius Soedharmo <arkatufus@yahoo.com>

* Fix serialization verification problem with Akka.IO messages (#4974)

* Fix serialization verification problem with Akka.IO messages

* Wrap naked SocketAsyncEventArgs in a struct that inherits INoSerializationVerificationNeeded

* Make the wrapper struct readonly

* Expand exception message with their actor types

* Update API Approver list

* ORDictionary with POCO value missing items, add MultiNode spec (#4910)

* Update DData reference HOCON config to follow JVM

* Clean up ReplicatorSettings, add sensible default values.

* Add DurableData spec that uses ORDictionary with POCO values

* Add a special case for Replicator to suppress messages during load

* Slight change in public API, behaviour is identical.

* Change Replicator class to UntypedActor

* Code cleanup - Change fields to properties

* Update API Approver list

* clean up seed node process (#4975)

* fixed racy ActorModelSpec (#4976)

fixed `A_dispatcher_must_handle_queuing_from_multiple_threads` - we were using the wrong message type the entire time, and the previous instance caused `Thread.Sleep` to be called repeatedly.

* Update PluginSpec so that it can accept ActorSystem and ActorSystemSetup in its constructor (#4978)

* Removed inaccurate warning from Cluster Singleton docs (#4980)

Cluster singletons won't create duplicates in a cluster split scenario, and it's much safer to run them _with_ a split brain resolver on than without. This documentation was just out of date.

* Introduce `ChannelExecutor` (#4882)

* added `ChannelExecutor` dispatcher - uses `FixedConcurrencyTaskScheduler` internally - have `ActorSystem.Create` call `ThreadPool.SetMinThreads(0,0)` to improve performance across the board.

* fixed documentation errors

* Upgrade to GitHub-native Dependabot (#4984)

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* added v1.4.19 release notes (#4985)

* added v1.4.19 release notes

Co-authored-by: Erik Følstad <32196030+ef-computas@users.noreply.github.com>
Co-authored-by: Erik Folstad <erikmafo@gmail.com>
Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: Igor <igor@fedchenko.pro>
Co-authored-by: Gregorius Soedharmo <arkatufus@yahoo.com>
Co-authored-by: zbynek001 <zbynek001@gmail.com>
Co-authored-by: Cagatay YILDIZOGLU <yildizoglu@gmail.com>
Co-authored-by: Ismael Hamed <1279846+ismaelhamed@users.noreply.github.com>
Co-authored-by: Anton V. Ilyin <iliyn.anton.v@gmail.com>
Co-authored-by: Arjen Smits <Deathraven163@gmail.com>
  • Loading branch information
11 people authored Apr 28, 2021
2 parents 4cbf1e2 + a3feeef commit 7a34a14
Show file tree
Hide file tree
Showing 187 changed files with 9,027 additions and 5,031 deletions.
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

0 comments on commit 7a34a14

Please sign in to comment.