net.adamec.lib.common.actor
1.0.0
See the version list below for details.
dotnet add package net.adamec.lib.common.actor --version 1.0.0
NuGet\Install-Package net.adamec.lib.common.actor -Version 1.0.0
<PackageReference Include="net.adamec.lib.common.actor" Version="1.0.0" />
paket add net.adamec.lib.common.actor --version 1.0.0
#r "nuget: net.adamec.lib.common.actor, 1.0.0"
// Install net.adamec.lib.common.actor as a Cake Addin #addin nuget:?package=net.adamec.lib.common.actor&version=1.0.0 // Install net.adamec.lib.common.actor as a Cake Tool #tool nuget:?package=net.adamec.lib.common.actor&version=1.0.0
Lightweight Actor System
The purpose is to provide the lightweight in-process asynchronous message based communication between the components (Inspired by Akka.net which provides actor system implementation for the applications where more robust solution is needed).
Actor is a generally any component implementing IActor
interface registered within the Actor System that is able to receive and process the messages sent from another Actor or even from outside world. The message processing is by design asynchronous where the messages for individual actors are processed in FIFO sequence, but the Actor System also provides the support for synchronous (Request-Reply) pattern.
Documentation at github Code documentation at github
High Level Architecture
Actor
is any object implementing IActor
interface publishing the method for processing the inbound messages. ActorSystem
is the main component taking care about the actors and distributing the messages. It's usually a singleton, but its possible to have multiple actor systems if needed.
Each actor must register to ActorSystem
first to get recognized by system (and deregister at the end of its life cycle). Actor System creates the internal reference to actor (ActorRefInternal
) and returns the IActorRef
interface used as a reference to Actor
within the Actor System. ActorRefInternal
object contains the reference to actor (IActor
) and encapsulates the MessageQueue
of actor. Anybody who has the reference to actor (IActorRef
) can send the message to actor using the method IActorRef.Tell
. The internal implementation encapsulates the message into the Envelope
and push it to the message queue related to the actor.
Actor system manages the ActorSystemDispatcher
running the executor thread responsible for checking the actors' message queues, pick the messages and deliver them to actors for processing.
Dispatcher periodically loops through the queues. If there is any message, the dispatcher uses the ThreadPool
to queue work item - process the messages for actor, so the messages for different actors can be processed in parallel in several threads. Whenever the actor is scheduled for processing, it's locked for further processing, until the scheduled processing task is finished.
The processing of actor messages is quite simple - message is picked from queue and sent to actor for processing (invoking the Receive
delegate returned by IActor.ReceiveTarget
). It waits until the message is processed, picks another message and send it to actor for processing. This ensures that the messages are processed sequentially in the order as they are enqueued (the message queue is FIFO). The system parameter max messages defines the size of single "batch" of messages to be processed before the actor is unlocked and waits for next "tick" of dispatcher.
Actor System maintains two system queues:
Deadletters
is the queue containing the messages that are not handled by actor or undeliverable. Whenever the message is sent to an actor for processing, the actor has to returntrue
if the message was processed orfalse
in case it didn't process (handle) the message. The unhandled messages are moved to dead letters queue then.ErrorMessageQueue
contains the messages that caused an exception while being processed by an actor. The exception is catched by dispatcher (exactly by scheduled work task distributing the messages to particular actor), encapsulated together with the message causing the exception intoErrorMessage
(inherits fromEnvelope
) and enqueued to the error message queue.
Scheduled Messages
Actor System supports scheduling of two types:
- One-time (non-periodical) messages are scheduled for given date and time. The dispatcher enqueues the message to recipient's queue next executor run after the defined date and time.
- Periodical messages are scheduled for given period. The dispatcher enqueues the message to recipient's queue next executor run after each period. Technically just the next message is scheduled for corresponding date and time and when it's equeued, another "instance" of scheduled message is created for the next period.
As describe above, you can't rely on the exact processing time of the scheduled messages, because the schedule tells when the message will be put into the queue (as the last message), so if there are any other messages pending in the queue, it will delay the message processing. Also the time when the messages are enqueued is not 100% exact - the dispatcher executor checks in each run (loop) for the scheduled messages with the next required fire time equal or older than current time so there is also small cost related to the dispatch of the messages.
Request-Reply Messaging
Astor System support Request-Reply messaging pattern using IActorSystem.Ask
methods. The temporary internal actor is created and the requested message is sent from this temporary actor to the recipient. When the recipient replies, the temporary actor check the type of response and if matches, it's "returned" back to the Ask
method and the temporary actor is dismissed.
In case that the required response doesn't come in given time period (timeout) the Ask
method returns default(T)
or throws TimeoutException
depending on given parameter.
So even if the message processing is "internally" asynchronous, the Ask
method is blocked (synchronous) and waits for the proper response or timeout.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- NLog (>= 4.5.11)
- RadCommons.extensions.TypeExtensions.DefaultValue (>= 1.1.0)
- RadCommons.logging.CommonLogging (>= 1.1.0)
- RadCommons.utils.BaseDisposable (>= 1.1.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.