lib. common. actor
Install-Package net.adamec.lib.common.actor -Version 1.0.1
dotnet add package net.adamec.lib.common.actor --version 1.0.1
<PackageReference Include="net.adamec.lib.common.actor" Version="1.0.1" />
paket add net.adamec.lib.common.actor --version 1.0.1
#r "nuget: net.adamec.lib.common.actor, 1.0.1"
// Install net.adamec.lib.common.actor as a Cake Addin #addin nuget:?package=net.adamec.lib.common.actor&version=1.0.1 // Install net.adamec.lib.common.actor as a Cake Tool #tool nuget:?package=net.adamec.lib.common.actor&version=1.0.1
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.
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.
ActorRefInternalobject 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:
Deadlettersis 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 return
trueif the message was processed or
falsein case it didn't process (handle) the message. The unhandled messages are moved to dead letters queue then.
ErrorMessageQueuecontains 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 into
Envelope) and enqueued to the error message queue.
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.
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
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.
- NLog (>= 4.5.11)
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.