Replace Rich Apostrophe with Standard Text (#214)
* Fix apostrophes * Fix apostrophes * Fix apostrophes * Fix apostrophes
This commit is contained in:
Родитель
7e5a5f0e02
Коммит
0fb84dd19c
|
@ -7,7 +7,7 @@ title: Fault tolerance
|
|||
As explained in [Actor Systems](ActorSystem) each actor is the supervisor of its
|
||||
children, and as such each actor defines fault handling supervisor strategy.
|
||||
This strategy cannot be changed afterwards as it is an integral part of the
|
||||
actor system’s structure.
|
||||
actor system's structure.
|
||||
|
||||
## Fault Handling in Practice
|
||||
|
||||
|
@ -135,7 +135,7 @@ terminated by the supervisor:
|
|||
|
||||
!!!TODO: Port sample code
|
||||
|
||||
Up to now the supervisor was completely unaffected by the child’s failure,
|
||||
Up to now the supervisor was completely unaffected by the child's failure,
|
||||
because the directives set did handle it. In case of an ``Exception``, this is not
|
||||
true anymore and the supervisor escalates the failure.
|
||||
|
||||
|
|
|
@ -225,10 +225,10 @@ This assumes that serialization happens in the context of sending a message
|
|||
through the remote transport. There are other uses of serialization, though,
|
||||
e.g. storing actor references outside of an actor application (database, etc.).
|
||||
In this case, it is important to keep in mind that the address part of an
|
||||
actor’s path determines how that actor is communicated with. Storing a local
|
||||
actor's path determines how that actor is communicated with. Storing a local
|
||||
actor path might be the right choice if the retrieval happens in the same
|
||||
logical context, but it is not enough when deserializing it on a different
|
||||
network host: for that it would need to include the system’s remote transport
|
||||
network host: for that it would need to include the system's remote transport
|
||||
address. An actor system is not limited to having just one remote transport
|
||||
per se, which makes this question a bit more interesting. To find out the
|
||||
appropriate address to use when sending to remoteAddr you can use
|
||||
|
@ -295,7 +295,7 @@ This requires that you know at least which type of address will be supported by
|
|||
the system which will deserialize the resulting actor reference; if you have no
|
||||
concrete address handy you can create a dummy one for the right protocol using
|
||||
new Address(protocol, "", "", 0) (assuming that the actual transport used is as
|
||||
lenient as Akka’s RemoteActorRefProvider).
|
||||
lenient as Akka's RemoteActorRefProvider).
|
||||
|
||||
There is also a default remote address which is the one used by cluster support
|
||||
(and typical systems have just this one); you can get it like this:
|
||||
|
|
|
@ -36,7 +36,7 @@ public class MyActor: ReceiveActor
|
|||
```
|
||||
|
||||
### The Inbox
|
||||
When writing code outside of actors which shall communicate with actors, the ask pattern can be a solution (see below), but there are two thing it cannot do: receiving multiple replies (e.g. by subscribing an `ActorRef` to a notification service) and watching other actors’ lifecycle. For these purposes there is the Inbox class:
|
||||
When writing code outside of actors which shall communicate with actors, the ask pattern can be a solution (see below), but there are two thing it cannot do: receiving multiple replies (e.g. by subscribing an `ActorRef` to a notification service) and watching other actors' lifecycle. For these purposes there is the Inbox class:
|
||||
|
||||
```csharp
|
||||
var target = system.ActorOf(Props.Empty);
|
||||
|
@ -54,7 +54,7 @@ catch (TimeoutException)
|
|||
}
|
||||
```
|
||||
|
||||
The send method wraps a normal tell and supplies the internal actor’s reference as the sender. This allows the reply to be received on the last line. Watching an actor is quite simple as well:
|
||||
The send method wraps a normal tell and supplies the internal actor's reference as the sender. This allows the reply to be received on the last line. Watching an actor is quite simple as well:
|
||||
|
||||
```csharp
|
||||
using System.Diagnostics;
|
||||
|
@ -76,7 +76,7 @@ catch (TimeoutException)
|
|||
## UntypedActor API
|
||||
The `UntypedActor` class defines only one abstract method, the above mentioned `OnReceive(object message)`, which implements the behavior of the actor.
|
||||
|
||||
If the current actor behavior does not match a received message, it's recommended that you call the unhandled method, which by default publishes a new `Akka.Actor.UnhandledMessage(message, sender, recipient)` on the actor system’s event stream (set configuration item `akka.actor.debug.unhandled` to on to have them converted into actual `Debug` messages).
|
||||
If the current actor behavior does not match a received message, it's recommended that you call the unhandled method, which by default publishes a new `Akka.Actor.UnhandledMessage(message, sender, recipient)` on the actor system's event stream (set configuration item `akka.actor.debug.unhandled` to on to have them converted into actual `Debug` messages).
|
||||
|
||||
In addition, it offers:
|
||||
|
||||
|
@ -86,7 +86,7 @@ In addition, it offers:
|
|||
|
||||
* `SupervisorStrategy` user overridable definition the strategy to use for supervising child actors
|
||||
|
||||
This strategy is typically declared inside the actor in order to have access to the actor’s internal state within the decider function: since failure is communicated as a message sent to the supervisor and processed like other messages (albeit outside of the normal behavior), all values and variables within the actor are available, as is the Sender reference (which will be the immediate child reporting the failure; if the original failure occurred within a distant descendant it is still reported one level up at a time).
|
||||
This strategy is typically declared inside the actor in order to have access to the actor's internal state within the decider function: since failure is communicated as a message sent to the supervisor and processed like other messages (albeit outside of the normal behavior), all values and variables within the actor are available, as is the Sender reference (which will be the immediate child reporting the failure; if the original failure occurred within a distant descendant it is still reported one level up at a time).
|
||||
|
||||
* `Context` exposes contextual information for the actor and the current message, such as:
|
||||
|
||||
|
@ -214,7 +214,7 @@ An example demonstrating remote actor look-up is given in Remoting Sample.
|
|||
actorFor is deprecated in favor of actorSelection because actor references acquired with actorFor behave differently for local and remote actors. In the case of a local actor reference, the named actor needs to exist before the lookup, or else the acquired reference will be an EmptyLocalActorRef. This will be true even if an actor with that exact path is created after acquiring the actor reference. For remote actor references acquired with actorFor the behaviour is different and sending messages to such a reference will under the hood look up the actor by path on the remote system for every message send.
|
||||
|
||||
## Messages and immutability
|
||||
**IMPORTANT:** Messages can be any kind of object but have to be immutable. Akka can’t enforce immutability (yet) so this has to be by convention.
|
||||
**IMPORTANT:** Messages can be any kind of object but have to be immutable. Akka can't enforce immutability (yet) so this has to be by convention.
|
||||
|
||||
Here is an example of an immutable message:
|
||||
|
||||
|
@ -248,7 +248,7 @@ In all these methods you have the option of passing along your own ActorRef. Mak
|
|||
This is the preferred way of sending messages. No blocking waiting for a message. This gives the best concurrency and scalability characteristics.
|
||||
|
||||
```csharp
|
||||
// don’t forget to think about who is the sender (2nd argument)
|
||||
// don't forget to think about who is the sender (2nd argument)
|
||||
target.Tell(message, Self);
|
||||
```
|
||||
The sender reference is passed along with the message and available within the receiving actor via its Sender property while processing this message. Inside of an actor it is usually Self who shall be the sender, but there can be cases where replies shall be routed to some other actor—e.g. the parent—in which the second argument to tell would be a different one. Outside of an actor and if no reply is needed the second argument can be null; if a reply is needed outside of an actor you can use the ask-pattern described next.
|
||||
|
@ -295,7 +295,7 @@ If the actor does not complete the task, it will expire after the timeout period
|
|||
For more information on Tasks, check out the [MSDN documentation](https://msdn.microsoft.com/en-us/library/dd537609(v=vs.110).aspx).
|
||||
|
||||
>**Warning**<br/>
|
||||
When using task callbacks inside actors, you need to carefully avoid closing over the containing actor’s reference, i.e. do not call methods or access mutable state on the enclosing actor from within the callback. This would break the actor encapsulation and may introduce synchronization bugs and race conditions because the callback will be scheduled concurrently to the enclosing actor. Unfortunately there is not yet a way to detect these illegal accesses at compile time. See also: [[Actors and shared mutable state]]
|
||||
When using task callbacks inside actors, you need to carefully avoid closing over the containing actor's reference, i.e. do not call methods or access mutable state on the enclosing actor from within the callback. This would break the actor encapsulation and may introduce synchronization bugs and race conditions because the callback will be scheduled concurrently to the enclosing actor. Unfortunately there is not yet a way to detect these illegal accesses at compile time. See also: [[Actors and shared mutable state]]
|
||||
|
||||
### Forward message
|
||||
You can forward a message from one actor to another. This means that the original sender address/reference is maintained even though the message is going through a 'mediator'. This can be useful when writing actors that work as routers, load-balancers, replicators etc. You need to pass along your context variable as well.
|
||||
|
@ -419,7 +419,7 @@ public class Manager : UntypedActor
|
|||
}
|
||||
```
|
||||
|
||||
When ```GracefulStop()``` returns successfully, the actor’s ```PostStop()``` hook will have been executed: there exists a happens-before edge between the end of ```PostStop()``` and the return of ```GracefulStop()```.
|
||||
When ```GracefulStop()``` returns successfully, the actor's ```PostStop()``` hook will have been executed: there exists a happens-before edge between the end of ```PostStop()``` and the return of ```GracefulStop()```.
|
||||
|
||||
In the above example a "shutdown" message is sent to the target actor to initiate the process of stopping the actor. You can use PoisonPill for this, but then you have limited possibilities to perform interactions with other actors before stopping the target actor. Simple cleanup tasks can be handled in PostStop.
|
||||
|
||||
|
@ -428,7 +428,7 @@ Keep in mind that an actor stopping and its name being deregistered are separate
|
|||
|
||||
## HotSwap
|
||||
### Upgrade
|
||||
Akka supports hotswapping the Actor’s message loop (e.g. its implementation) at runtime. Use the Context.Become method from within the Actor. The hotswapped code is kept in a Stack which can be pushed (replacing or adding at the top) and popped.
|
||||
Akka supports hotswapping the Actor's message loop (e.g. its implementation) at runtime. Use the Context.Become method from within the Actor. The hotswapped code is kept in a Stack which can be pushed (replacing or adding at the top) and popped.
|
||||
|
||||
>**Warning**<br/>
|
||||
Please note that the actor will revert to its original behavior when restarted by its Supervisor.
|
||||
|
@ -533,7 +533,7 @@ If an exception is thrown while a message is being processed (i.e. taken out of
|
|||
If an exception is thrown while a message is being processed, nothing happens to the mailbox. If the actor is restarted, the same mailbox will be there. So all messages on that mailbox will be there as well.
|
||||
|
||||
### What happens to the actor
|
||||
If code within an actor throws an exception, that actor is suspended and the supervision process is started (see Supervision and Monitoring). Depending on the supervisor’s decision the actor is resumed (as if nothing happened), restarted (wiping out its internal state and starting from scratch) or terminated.
|
||||
If code within an actor throws an exception, that actor is suspended and the supervision process is started (see Supervision and Monitoring). Depending on the supervisor's decision the actor is resumed (as if nothing happened), restarted (wiping out its internal state and starting from scratch) or terminated.
|
||||
|
||||
## Initialization patterns
|
||||
The rich lifecycle hooks of Actors provide a useful toolkit to implement various initialization patterns. During the lifetime of an ActorRef, an actor can potentially go through several restarts, where the old instance is replaced by a fresh one, invisibly to the outside observer who only sees the ActorRef.
|
||||
|
|
|
@ -17,9 +17,9 @@ As detailed below, an actor object needs to be shielded from the outside in orde
|
|||
## State
|
||||
Actor objects will typically contain some variables which reflect possible states the actor may be in. This can be an explicit state machine (e.g. using the FSM module), or it could be a counter, set of listeners, pending requests, etc. These data are what make an actor valuable, and they must be protected from corruption by other actors. The good news is that Akka.NET actors conceptually each have their own light-weight thread, which is completely shielded from the rest of the system. This means that instead of having to synchronize access using locks you can just write your actor code without worrying about concurrency at all.
|
||||
|
||||
Behind the scenes Akka.NET will run sets of actors on sets of real threads, where typically many actors share one thread, and subsequent invocations of one actor may end up being processed on different threads. Akka.NET ensures that this implementation detail does not affect the single-threadedness of handling the actor’s state.
|
||||
Behind the scenes Akka.NET will run sets of actors on sets of real threads, where typically many actors share one thread, and subsequent invocations of one actor may end up being processed on different threads. Akka.NET ensures that this implementation detail does not affect the single-threadedness of handling the actor's state.
|
||||
|
||||
Because the internal state is vital to an actor’s operations, having inconsistent state is fatal. Thus, when the actor fails and is restarted by its supervisor, the state will be created from scratch, like upon first creating the actor. This is to enable the ability of self-healing of the system.
|
||||
Because the internal state is vital to an actor's operations, having inconsistent state is fatal. Thus, when the actor fails and is restarted by its supervisor, the state will be created from scratch, like upon first creating the actor. This is to enable the ability of self-healing of the system.
|
||||
|
||||
Optionally, an actor's state can be automatically recovered to the state before a restart by persisting received messages and replaying them after restart (see Persistence).
|
||||
|
||||
|
@ -27,14 +27,14 @@ Optionally, an actor's state can be automatically recovered to the state before
|
|||
Every time a message is processed, it is matched against the current behavior of the actor. Behavior means a function which defines the actions to be taken in reaction to the message at that point in time, say forward a request if the client is authorized, deny it otherwise. This behavior may change over time, e.g. because different clients obtain authorization over time, or because the actor may go into an “out-of-service” mode and later come back. These changes are achieved by either encoding them in state variables which are read from the behavior logic, or the function itself may be swapped out at runtime, see the become and unbecome operations. However, the initial behavior defined during construction of the actor object is special in the sense that a restart of the actor will reset its behavior to this initial one.
|
||||
|
||||
## Mailbox
|
||||
An actor’s purpose is the processing of messages, and these messages were sent to the actor from other actors (or from outside the actor system). The piece which connects sender and receiver is the actor’s mailbox: each actor has exactly one mailbox to which all senders enqueue their messages. Enqueuing happens in the time-order of send operations, which means that messages sent from different actors may not have a defined order at runtime due to the apparent randomness of distributing actors across threads. Sending multiple messages to the same target from the same actor, on the other hand, will enqueue them in the same order.
|
||||
An actor's purpose is the processing of messages, and these messages were sent to the actor from other actors (or from outside the actor system). The piece which connects sender and receiver is the actor's mailbox: each actor has exactly one mailbox to which all senders enqueue their messages. Enqueuing happens in the time-order of send operations, which means that messages sent from different actors may not have a defined order at runtime due to the apparent randomness of distributing actors across threads. Sending multiple messages to the same target from the same actor, on the other hand, will enqueue them in the same order.
|
||||
|
||||
There are different mailbox implementations to choose from, the default being a FIFO: the order of the messages processed by the actor matches the order in which they were enqueued. This is usually a good default, but applications may need to prioritize some messages over others. In this case, a priority mailbox will enqueue not always at the end but at a position as given by the message priority, which might even be at the front. While using such a queue, the order of messages processed will naturally be defined by the queue’s algorithm and in general not be FIFO.
|
||||
There are different mailbox implementations to choose from, the default being a FIFO: the order of the messages processed by the actor matches the order in which they were enqueued. This is usually a good default, but applications may need to prioritize some messages over others. In this case, a priority mailbox will enqueue not always at the end but at a position as given by the message priority, which might even be at the front. While using such a queue, the order of messages processed will naturally be defined by the queue's algorithm and in general not be FIFO.
|
||||
|
||||
An important feature in which Akka.NET differs from some other actor model implementations is that the current behavior must always handle the next dequeued message, there is no scanning the mailbox for the next matching one. Failure to handle a message will typically be treated as a failure, unless this behavior is overridden.
|
||||
|
||||
## Children
|
||||
Each actor is potentially a supervisor: if it creates children for delegating sub-tasks, it will automatically supervise them. The list of children is maintained within the actor’s context and the actor has access to it. Modifications to the list are done by creating (`Context.ActorOf(...)`) or stopping (`Context.Stop(child)`) children and these actions are reflected immediately. The actual creation and termination actions happen behind the scenes in an asynchronous way, so they do not “block” their supervisor.
|
||||
Each actor is potentially a supervisor: if it creates children for delegating sub-tasks, it will automatically supervise them. The list of children is maintained within the actor's context and the actor has access to it. Modifications to the list are done by creating (`Context.ActorOf(...)`) or stopping (`Context.Stop(child)`) children and these actions are reflected immediately. The actual creation and termination actions happen behind the scenes in an asynchronous way, so they do not “block” their supervisor.
|
||||
|
||||
## Supervisor Strategy
|
||||
The final piece of an actor is its strategy for handling faults of its children. Fault handling is then done transparently by Akka, applying one of the strategies described in Supervision and Monitoring for each incoming failure. As this strategy is fundamental to how an actor system is structured, it cannot be changed once an actor has been created.
|
||||
|
@ -42,6 +42,6 @@ The final piece of an actor is its strategy for handling faults of its children.
|
|||
Considering that there is only one such strategy for each actor, this means that if different strategies apply to the various children of an actor, the children should be grouped beneath intermediate supervisors with matching strategies, preferring once more the structuring of actor systems according to the splitting of tasks into sub-tasks.
|
||||
|
||||
## When an Actor Terminates
|
||||
Once an actor terminates, i.e. fails in a way which is not handled by a restart, stops itself or is stopped by its supervisor, it will free up its resources, draining all remaining messages from its mailbox into the system’s “dead letter mailbox” which will forward them to the `EventStream` as `DeadLetters`. The mailbox is then replaced within the actor reference with a system mailbox, redirecting all new messages to the `EventStream` as `DeadLetters`. This is done on a best effort basis, though, so do not rely on it in order to construct “guaranteed delivery”.
|
||||
Once an actor terminates, i.e. fails in a way which is not handled by a restart, stops itself or is stopped by its supervisor, it will free up its resources, draining all remaining messages from its mailbox into the system's “dead letter mailbox” which will forward them to the `EventStream` as `DeadLetters`. The mailbox is then replaced within the actor reference with a system mailbox, redirecting all new messages to the `EventStream` as `DeadLetters`. This is done on a best effort basis, though, so do not rely on it in order to construct “guaranteed delivery”.
|
||||
|
||||
The reason for not just silently dumping the messages was inspired by our tests: we register the TestEventListener on the event bus to which the dead letters are forwarded, and that will log a warning for every dead letter received—this has been very helpful for deciphering test failures more quickly. It is conceivable that this feature may also be of use for other purposes.
|
|
@ -5,7 +5,7 @@ title: Actor Systems
|
|||
|
||||
# Actor Systems
|
||||
|
||||
[Actors](actors) are objects which encapsulate state and behavior, they communicate exclusively by exchanging [messages](messages) which are placed into the recipient’s mailbox. In a sense, actors are the most stringent form of object-oriented programming, but it serves better to view them as persons: while modeling a solution with actors, envision a group of people and assign sub-tasks to them, arrange their functions into an organizational structure and think about how to escalate failure (all with the benefit of not actually dealing with people, which means that we need not concern ourselves with their emotional state or moral issues). The result can then serve as a mental scaffolding for building the software implementation.
|
||||
[Actors](actors) are objects which encapsulate state and behavior, they communicate exclusively by exchanging [messages](messages) which are placed into the recipient's mailbox. In a sense, actors are the most stringent form of object-oriented programming, but it serves better to view them as persons: while modeling a solution with actors, envision a group of people and assign sub-tasks to them, arrange their functions into an organizational structure and think about how to escalate failure (all with the benefit of not actually dealing with people, which means that we need not concern ourselves with their emotional state or moral issues). The result can then serve as a mental scaffolding for building the software implementation.
|
||||
|
||||
>**Note**<br/>
|
||||
>An `ActorSystem` is a heavyweight structure that will allocate 1...N Threads, so create one per logical application.
|
||||
|
@ -23,7 +23,7 @@ Now, the difficulty in designing such a system is how to decide who should super
|
|||
|
||||
* If one actor manages the work another actor is doing, e.g. by passing on sub-tasks, then the manager should supervise the child. The reason is that the manager knows which kind of failures are expected and how to handle them.
|
||||
* If one actor carries very important data (i.e. its state shall not be lost if avoidable), this actor should source out any possibly dangerous sub-tasks to children it supervises and handle failures of these children as appropriate. Depending on the nature of the requests, it may be best to create a new child for each request, which simplifies state management for collecting the replies. This is known as the “Error Kernel Pattern” from Erlang.
|
||||
* If one actor depends on another actor for carrying out its duty, it should watch that other actor’s liveness and act upon receiving a termination notice. This is different from supervision, as the watching party has no influence on the supervisor strategy, and it should be noted that a functional dependency alone is not a criterion for deciding where to place a certain child actor in the hierarchy.
|
||||
* If one actor depends on another actor for carrying out its duty, it should watch that other actor's liveness and act upon receiving a termination notice. This is different from supervision, as the watching party has no influence on the supervisor strategy, and it should be noted that a functional dependency alone is not a criterion for deciding where to place a certain child actor in the hierarchy.
|
||||
There are of course always exceptions to these rules, but no matter whether you follow the rules or break them, you should always have a reason.
|
||||
|
||||
## Configuration Container
|
||||
|
|
|
@ -29,12 +29,12 @@ There is an actor reference which does not represent an actor but acts only as a
|
|||
The first logging service started before actually firing up actor creation facilities is a fake actor reference which accepts log events and prints them directly to standard output; it is `Logging.StandardOutLogger`.
|
||||
|
||||
## What is an Actor Path?
|
||||
Since actors are created in a strictly hierarchical fashion, there exists a unique sequence of actor names given by recursively following the supervision links between child and parent down towards the root of the actor system. This sequence can be seen as enclosing folders in a file system, hence we adopted the name “path” to refer to it. As in some real file-systems there also are “symbolic links”, i.e. one actor may be reachable using more than one path, where all but one involve some translation which decouples part of the path from the actor’s actual supervision ancestor line; these specialities are described in the sub-sections to follow.
|
||||
Since actors are created in a strictly hierarchical fashion, there exists a unique sequence of actor names given by recursively following the supervision links between child and parent down towards the root of the actor system. This sequence can be seen as enclosing folders in a file system, hence we adopted the name “path” to refer to it. As in some real file-systems there also are “symbolic links”, i.e. one actor may be reachable using more than one path, where all but one involve some translation which decouples part of the path from the actor's actual supervision ancestor line; these specialities are described in the sub-sections to follow.
|
||||
|
||||
An actor path consists of an anchor, which identifies the actor system, followed by the concatenation of the path elements, from root guardian to the designated actor; the path elements are the names of the traversed actors and are separated by slashes.
|
||||
|
||||
### What is the Difference Between Actor Reference and Path?
|
||||
An actor reference designates a single actor and the life-cycle of the reference matches that actor’s life-cycle; an actor path represents a name which may or may not be inhabited by an actor and the path itself does not have a life-cycle, it never becomes invalid. You can create an actor path without creating an actor, but you cannot create an actor reference without creating corresponding actor.
|
||||
An actor reference designates a single actor and the life-cycle of the reference matches that actor's life-cycle; an actor path represents a name which may or may not be inhabited by an actor and the path itself does not have a life-cycle, it never becomes invalid. You can create an actor path without creating an actor, but you cannot create an actor reference without creating corresponding actor.
|
||||
|
||||
>**Note**<br/>
|
||||
>That definition does not hold for actorFor, which is one of the reasons why actorFor is deprecated in favor of actorSelection.
|
||||
|
@ -51,7 +51,7 @@ Each actor path has an address component, describing the protocol and location b
|
|||
Here, `akka.tcp` is the default remote transport for the 1.0 release; other transports are pluggable. A remote host using UDP would be accessible by using akka.udp. The interpretation of the host and port part (i.e.``serv.example.com:5678`` in the example) depends on the transport mechanism used, but it must abide by the URI structural rules.
|
||||
|
||||
### Logical Actor Paths
|
||||
The unique path obtained by following the parental supervision links towards the root guardian is called the logical actor path. This path matches exactly the creation ancestry of an actor, so it is completely deterministic as soon as the actor system’s remoting configuration (and with it the address component of the path) is set.
|
||||
The unique path obtained by following the parental supervision links towards the root guardian is called the logical actor path. This path matches exactly the creation ancestry of an actor, so it is completely deterministic as soon as the actor system's remoting configuration (and with it the address component of the path) is set.
|
||||
|
||||
### Physical Actor Paths
|
||||
While the logical actor path describes the functional location within one actor system, configuration-based remote deployment means that an actor may be created on a different network host than its parent, i.e. within a different actor system. In this case, following the actor path from the root guardian up entails traversing the network, which is a costly operation. Therefore, each actor also has a physical path, starting at the root guardian of the actor system where the actual actor object resides. Using this path as sender reference when querying other actors will let them reply directly to this actor, minimizing delays incurred by routing.
|
||||
|
@ -103,17 +103,17 @@ If you need to keep track of actor references in a collection and do not care ab
|
|||
## Reusing Actor Paths
|
||||
When an actor is terminated, its reference will point to the dead letter mailbox, DeathWatch will publish its final transition and in general it is not expected to come back to life again (since the actor life cycle does not allow this). While it is possible to create an actor at a later time with an identical path—simply due to it being impossible to enforce the opposite without keeping the set of all actors ever created available—this is not good practice.
|
||||
|
||||
It may be the right thing to do in very specific circumstances, but make sure to confine the handling of this precisely to the actor’s supervisor, because that is the only actor which can reliably detect proper deregistration of the name, before which creation of the new child will fail.
|
||||
It may be the right thing to do in very specific circumstances, but make sure to confine the handling of this precisely to the actor's supervisor, because that is the only actor which can reliably detect proper deregistration of the name, before which creation of the new child will fail.
|
||||
|
||||
It may also be required during testing, when the test subject depends on being instantiated at a specific path. In that case it is best to mock its supervisor so that it will forward the Terminated message to the appropriate point in the test procedure, enabling the latter to await proper deregistration of the name.
|
||||
|
||||
## The Interplay with Remote Deployment
|
||||
When an actor creates a child, the actor system’s deployer will decide whether the new actor resides in the same CLR or on another node. In the second case, creation of the actor will be triggered via a network connection to happen in a different CLR and consequently within a different actor system. The remote system will place the new actor below a special path reserved for this purpose and the supervisor of the new actor will be a remote actor reference (representing that actor which triggered its creation). In this case, context.parent (the supervisor reference) and context.path.parent (the parent node in the actor’s path) do not represent the same actor. However, looking up the child’s name within the supervisor will find it on the remote node, preserving logical structure e.g. when sending to an unresolved actor reference.
|
||||
When an actor creates a child, the actor system's deployer will decide whether the new actor resides in the same CLR or on another node. In the second case, creation of the actor will be triggered via a network connection to happen in a different CLR and consequently within a different actor system. The remote system will place the new actor below a special path reserved for this purpose and the supervisor of the new actor will be a remote actor reference (representing that actor which triggered its creation). In this case, context.parent (the supervisor reference) and context.path.parent (the parent node in the actor's path) do not represent the same actor. However, looking up the child's name within the supervisor will find it on the remote node, preserving logical structure e.g. when sending to an unresolved actor reference.
|
||||
|
||||
![Remote Deployment](../images/RemoteDeployment.png)
|
||||
|
||||
## What is the Address part used for?
|
||||
When sending an actor reference across the network, it is represented by its path. Hence, the path must fully encode all information necessary to send messages to the underlying actor. This is achieved by encoding protocol, host and port in the address part of the path string. When an actor system receives an actor path from a remote node, it checks whether that path’s address matches the address of this actor system, in which case it will be resolved to the actor’s local reference. Otherwise, it will be represented by a remote actor reference.
|
||||
When sending an actor reference across the network, it is represented by its path. Hence, the path must fully encode all information necessary to send messages to the underlying actor. This is achieved by encoding protocol, host and port in the address part of the path string. When an actor system receives an actor path from a remote node, it checks whether that path's address matches the address of this actor system, in which case it will be resolved to the actor's local reference. Otherwise, it will be represented by a remote actor reference.
|
||||
|
||||
## Top-Level Scopes for Actor Paths
|
||||
At the root of the path hierarchy resides the root guardian above which all other actors are found; its name is `"/"`. The next level consists of the following:
|
||||
|
|
|
@ -26,7 +26,7 @@ remote transport will place a limit on the message size.
|
|||
Writing your actors such that every interaction could possibly be remote is the
|
||||
safe, pessimistic bet. It means to only rely on those properties which are
|
||||
always guaranteed and which are discussed in detail below. This has of course
|
||||
some overhead in the actor’s implementation. If you are willing to sacrifice full
|
||||
some overhead in the actor's implementation. If you are willing to sacrifice full
|
||||
location transparency—for example in case of a group of closely collaborating
|
||||
actors—you can place them always on the same local application and enjoy stricter guarantees
|
||||
on message delivery. The details of this trade-off are discussed further below.
|
||||
|
@ -130,8 +130,8 @@ illustrated in the following:
|
|||
6) Since there is no guaranteed delivery, any of the messages may be dropped, i.e. not arrive at ``A2``
|
||||
|
||||
>**Note**<br/>
|
||||
It is important to note that Akka’s guarantee applies to the order in which
|
||||
messages are enqueued into the recipient’s mailbox. If the mailbox
|
||||
It is important to note that Akka's guarantee applies to the order in which
|
||||
messages are enqueued into the recipient's mailbox. If the mailbox
|
||||
implementation does not respect FIFO order (e.g. a `PriorityMailbox`),
|
||||
then the order of processing by the actor can deviate from the enqueueing
|
||||
order.
|
||||
|
@ -222,7 +222,7 @@ possibly non-exhaustive list of counter-indications is:
|
|||
- Before receiving the first reply from a top-level actor, there is a lock
|
||||
which protects an internal interim queue, and this lock is not fair; the
|
||||
implication is that enqueue requests from different senders which arrive
|
||||
during the actor’s construction (figuratively, the details are more involved)
|
||||
during the actor's construction (figuratively, the details are more involved)
|
||||
may be reordered depending on low-level thread scheduling. Since completely
|
||||
fair locks do not exist on the CLR this is unfixable.
|
||||
|
||||
|
@ -276,11 +276,11 @@ Event sourcing (and sharding) is what makes large websites scale to
|
|||
billions of users, and the idea is quite simple: when a component (think actor)
|
||||
processes a command it will generate a list of events representing the effect
|
||||
of the command. These events are stored in addition to being applied to the
|
||||
component’s state. The nice thing about this scheme is that events only ever
|
||||
component's state. The nice thing about this scheme is that events only ever
|
||||
are appended to the storage, nothing is ever mutated; this enables perfect
|
||||
replication and scaling of consumers of this event stream (i.e. other
|
||||
components may consume the event stream as a means to replicate the component’s
|
||||
state on a different continent or to react to changes). If the component’s
|
||||
components may consume the event stream as a means to replicate the component's
|
||||
state on a different continent or to react to changes). If the component's
|
||||
state is lost—due to a machine failure or by being pushed out of a cache—it can
|
||||
easily be reconstructed by replaying the event stream (usually employing
|
||||
snapshots to speed up the process). :ref:`event-sourcing` is supported by
|
||||
|
@ -289,9 +289,9 @@ Akka.NET Persistence.
|
|||
###Mailbox with Explicit Acknowledgement
|
||||
|
||||
By implementing a custom mailbox type it is possible retry message processing
|
||||
at the receiving actor’s end in order to handle temporary failures. This
|
||||
at the receiving actor's end in order to handle temporary failures. This
|
||||
pattern is mostly useful in the local communication context where delivery
|
||||
guarantees are otherwise sufficient to fulfill the application’s requirements.
|
||||
guarantees are otherwise sufficient to fulfill the application's requirements.
|
||||
|
||||
Please note that the caveats for `The Rules for In-App (Local) Message Sends`_
|
||||
do apply.
|
||||
|
@ -316,7 +316,7 @@ deadLetters where possible, i.e. run your application with a suitable dead
|
|||
letter logger (see more below) from time to time and clean up the log output.
|
||||
This exercise—like all else—requires judicious application of common sense: it
|
||||
may well be that avoiding to send to a terminated actor complicates the
|
||||
sender’s code more than is gained in debug output clarity.
|
||||
sender's code more than is gained in debug output clarity.
|
||||
|
||||
The dead letter service follows the same rules with respect to delivery
|
||||
guarantees as all other message sends, hence it cannot be used to implement
|
||||
|
|
|
@ -17,7 +17,7 @@ As described in [Actor Systems](actorsystems) supervision describes a dependency
|
|||
|
||||
It is important to always view an actor as part of a supervision hierarchy, which explains the existence of the fourth choice (as a supervisor also is subordinate to another supervisor higher up) and has implications on the first three: resuming an actor resumes all its subordinates, restarting an actor entails restarting all its subordinates (but see below for more details), similarly terminating an actor will also terminate all its subordinates. It should be noted that the default behavior of the `PreRestart` hook of the Actor class is to terminate all its children before restarting, but this hook can be overridden; the recursive restart applies to all children left after this hook has been executed.
|
||||
|
||||
Each supervisor is configured with a function translating all possible failure causes (i.e. exceptions) into one of the four choices given above; notably, this function does not take the failed actor’s identity as an input. It is quite easy to come up with examples of structures where this might not seem flexible enough, e.g. wishing for different strategies to be applied to different subordinates. At this point it is vital to understand that supervision is about forming a recursive fault handling structure. If you try to do too much at one level, it will become hard to reason about, hence the recommended way in this case is to add a level of supervision.
|
||||
Each supervisor is configured with a function translating all possible failure causes (i.e. exceptions) into one of the four choices given above; notably, this function does not take the failed actor's identity as an input. It is quite easy to come up with examples of structures where this might not seem flexible enough, e.g. wishing for different strategies to be applied to different subordinates. At this point it is vital to understand that supervision is about forming a recursive fault handling structure. If you try to do too much at one level, it will become hard to reason about, hence the recommended way in this case is to add a level of supervision.
|
||||
|
||||
Akka.NET implements a specific form called “parental supervision”. Actors can only be created by other actors—where the top-level actor is provided by the library—and each created actor is supervised by its parent. This restriction makes the formation of actor supervision hierarchies implicit and encourages sound design decisions. It should be noted that this also guarantees that actors cannot be orphaned or attached to supervisors from the outside, which might otherwise catch them unawares. In addition, this yields a natural and clean shutdown procedure for (sub-trees of) actor applications.
|
||||
|
||||
|
@ -34,13 +34,13 @@ Akka.NET implements a specific form called “parental supervision”. Actors ca
|
|||
An actor system will during its creation start at least three actors, shown in the image above. For more information about the consequences for actor paths see Top-Level Scopes for Actor Paths.
|
||||
|
||||
### `/user`: The Guardian Actor
|
||||
The actor which is probably most interacted with is the parent of all user-created actors, the guardian named `"/user"`. Actors created using `system.ActorOf()` are children of this actor. This means that when this guardian terminates, all normal actors in the system will be shutdown, too. It also means that this guardian’s supervisor strategy determines how the top-level normal actors are supervised. Since Akka.NET 1.0 it is possible to configure this using the setting `akka.actor.guardian-supervisor-strategy`, which takes the fully-qualified class-name of a `SupervisorStrategyConfigurator`. When the guardian escalates a failure, the root guardian’s response will be to terminate the guardian, which in effect will shut down the whole actor system.
|
||||
The actor which is probably most interacted with is the parent of all user-created actors, the guardian named `"/user"`. Actors created using `system.ActorOf()` are children of this actor. This means that when this guardian terminates, all normal actors in the system will be shutdown, too. It also means that this guardian's supervisor strategy determines how the top-level normal actors are supervised. Since Akka.NET 1.0 it is possible to configure this using the setting `akka.actor.guardian-supervisor-strategy`, which takes the fully-qualified class-name of a `SupervisorStrategyConfigurator`. When the guardian escalates a failure, the root guardian's response will be to terminate the guardian, which in effect will shut down the whole actor system.
|
||||
|
||||
### `/system`: The System Guardian
|
||||
This special guardian has been introduced in order to achieve an orderly shut-down sequence where logging remains active while all normal actors terminate, even though logging itself is implemented using actors. This is realized by having the system guardian watch the user guardian and initiate its own shut-down upon reception of the `Terminated` message. The top-level system actors are supervised using a strategy which will restart indefinitely upon all types of Exception except for `ActorInitializationException` and `ActorKilledException`, which will terminate the child in question. All other exceptions are escalated, which will shut down the whole actor system.
|
||||
|
||||
### `/`: The Root Guardian
|
||||
The root guardian is the grand-parent of all so-called “top-level” actors and supervises all the special actors mentioned in Top-Level Scopes for Actor Paths using the `SupervisorStrategy.StoppingStrategy`, whose purpose is to terminate the child upon any type of Exception. All other throwables will be escalated … but to whom? Since every real actor has a supervisor, the supervisor of the root guardian cannot be a real actor. And because this means that it is “outside of the bubble”, it is called the “bubble-walker”. This is a synthetic ActorRef which in effect stops its child upon the first sign of trouble and sets the actor system’s isTerminated status to true as soon as the root guardian is fully terminated (all children recursively stopped).
|
||||
The root guardian is the grand-parent of all so-called “top-level” actors and supervises all the special actors mentioned in Top-Level Scopes for Actor Paths using the `SupervisorStrategy.StoppingStrategy`, whose purpose is to terminate the child upon any type of Exception. All other throwables will be escalated … but to whom? Since every real actor has a supervisor, the supervisor of the root guardian cannot be a real actor. And because this means that it is “outside of the bubble”, it is called the “bubble-walker”. This is a synthetic ActorRef which in effect stops its child upon the first sign of trouble and sets the actor system's isTerminated status to true as soon as the root guardian is fully terminated (all children recursively stopped).
|
||||
|
||||
## What Restarting Means
|
||||
When presented with an actor which failed while processing a certain message, causes for the failure fall into three categories:
|
||||
|
@ -49,12 +49,12 @@ When presented with an actor which failed while processing a certain message, ca
|
|||
* (Transient) failure of some external resource used during processing the message
|
||||
* Corrupt internal state of the actor
|
||||
|
||||
Unless the failure is specifically recognizable, the third cause cannot be ruled out, which leads to the conclusion that the internal state needs to be cleared out. If the supervisor decides that its other children or itself is not affected by the corruption—e.g. because of conscious application of the error kernel pattern—it is therefore best to restart the child. This is carried out by creating a new instance of the underlying Actor class and replacing the failed instance with the fresh one inside the child’s `ActorRef`; the ability to do this is one of the reasons for encapsulating actors within special references. The new actor then resumes processing its mailbox, meaning that the restart is not visible outside of the actor itself with the notable exception that the message during which the failure occurred is not re-processed.
|
||||
Unless the failure is specifically recognizable, the third cause cannot be ruled out, which leads to the conclusion that the internal state needs to be cleared out. If the supervisor decides that its other children or itself is not affected by the corruption—e.g. because of conscious application of the error kernel pattern—it is therefore best to restart the child. This is carried out by creating a new instance of the underlying Actor class and replacing the failed instance with the fresh one inside the child's `ActorRef`; the ability to do this is one of the reasons for encapsulating actors within special references. The new actor then resumes processing its mailbox, meaning that the restart is not visible outside of the actor itself with the notable exception that the message during which the failure occurred is not re-processed.
|
||||
|
||||
The precise sequence of events during a restart is the following:
|
||||
|
||||
1. Suspend the actor (which means that it will not process normal messages until resumed), and recursively suspend all children.
|
||||
2. Call the old instance’s `PreRestart` hook (defaults to sending termination requests to all children and calling postStop)
|
||||
2. Call the old instance's `PreRestart` hook (defaults to sending termination requests to all children and calling postStop)
|
||||
3. Wait for all children which were requested to terminate (using `context.Stop()`) during `PreRestart` to actually terminate; this—like all actor operations—is non-blocking, the termination notice from the last killed child will effect the progression to the next step.
|
||||
4. Create new actor instance by invoking the originally provided factory again.
|
||||
5. Invoke `PostRestart` on the new instance (which by default also calls `PreStart`)
|
||||
|
@ -65,9 +65,9 @@ The precise sequence of events during a restart is the following:
|
|||
>**Note**<br/>
|
||||
>Lifecycle Monitoring in Akka.NET is usually referred to as `DeathWatch`
|
||||
|
||||
In contrast to the special relationship between parent and child described above, each actor may monitor any other actor. Since actors emerge from creation fully alive and restarts are not visible outside of the affected supervisors, the only state change available for monitoring is the transition from alive to dead. Monitoring is thus used to tie one actor to another so that it may react to the other actor’s termination, in contrast to supervision which reacts to failure.
|
||||
In contrast to the special relationship between parent and child described above, each actor may monitor any other actor. Since actors emerge from creation fully alive and restarts are not visible outside of the affected supervisors, the only state change available for monitoring is the transition from alive to dead. Monitoring is thus used to tie one actor to another so that it may react to the other actor's termination, in contrast to supervision which reacts to failure.
|
||||
|
||||
Lifecycle monitoring is implemented using a `Terminated` message to be received by the monitoring actor, where the default behavior is to throw a special `DeathPactException` if not otherwise handled. In order to start listening for Terminated messages, invoke `ActorContext.Watch(targetActorRef)`. To stop listening, invoke `ActorContext.Unwatch(targetActorRef)`. One important property is that the message will be delivered irrespective of the order in which the monitoring request and target’s termination occur, i.e. you still get the message even if at the time of registration the target is already dead.
|
||||
Lifecycle monitoring is implemented using a `Terminated` message to be received by the monitoring actor, where the default behavior is to throw a special `DeathPactException` if not otherwise handled. In order to start listening for Terminated messages, invoke `ActorContext.Watch(targetActorRef)`. To stop listening, invoke `ActorContext.Unwatch(targetActorRef)`. One important property is that the message will be delivered irrespective of the order in which the monitoring request and target's termination occur, i.e. you still get the message even if at the time of registration the target is already dead.
|
||||
|
||||
Monitoring is particularly useful if a supervisor cannot simply restart its children and has to terminate them, e.g. in case of errors during actor initialization. In that case it should monitor those children and re-create them or schedule itself to retry this at a later time.
|
||||
|
||||
|
@ -78,7 +78,7 @@ There are two classes of supervision strategies which come with Akka: `OneForOne
|
|||
|
||||
![One for one](../images/OneForOne.png)
|
||||
|
||||
The `AllForOneStrategy` is applicable in cases where the ensemble of children has such tight dependencies among them, that a failure of one child affects the function of the others, i.e. they are inextricably linked. Since a restart does not clear out the mailbox, it often is best to terminate the children upon failure and re-create them explicitly from the supervisor (by watching the children’s lifecycle); otherwise you have to make sure that it is no problem for any of the actors to receive a message which was queued before the restart but processed afterwards.
|
||||
The `AllForOneStrategy` is applicable in cases where the ensemble of children has such tight dependencies among them, that a failure of one child affects the function of the others, i.e. they are inextricably linked. Since a restart does not clear out the mailbox, it often is best to terminate the children upon failure and re-create them explicitly from the supervisor (by watching the children's lifecycle); otherwise you have to make sure that it is no problem for any of the actors to receive a message which was queued before the restart but processed afterwards.
|
||||
|
||||
![All for one](../images/AllForOne.png)
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ Akka persistence query complements Persistence by providing a universal asynchro
|
|||
The most typical use case of persistence query is implementing the so-called query side (also known as "read side") in the popular CQRS architecture pattern - in which the writing side of the application (e.g. implemented using akka persistence) is completely separated from the "query side". Akka Persistence Query itself is not directly the query side of an application, however it can help to migrate data from the write side to the query side database. In very simple scenarios Persistence Query may be powerful enough to fulfill the query needs of your app, however we highly recommend (in the spirit of CQRS) of splitting up the write/read sides into separate datastores as the need arises.
|
||||
|
||||
> **Warning** <br>
|
||||
This module is marked as “experimental” as of its introduction in Akka.Net 1.1.0. We will continue to improve this API based on our users’ feedback, which implies that while we try to keep incompatible changes to a minimum the binary compatibility guarantee for maintenance releases does not apply to the contents of the Akka.Persistence.Query package.
|
||||
This module is marked as “experimental” as of its introduction in Akka.Net 1.1.0. We will continue to improve this API based on our users' feedback, which implies that while we try to keep incompatible changes to a minimum the binary compatibility guarantee for maintenance releases does not apply to the contents of the Akka.Persistence.Query package.
|
||||
|
||||
## Design overview
|
||||
Akka Persistence Query is purposely designed to be a very loosely specified API. This is in order to keep the provided APIs general enough for each journal implementation to be able to expose its best features, e.g. a SQL journal can use complex SQL queries or if a journal is able to subscribe to a live event stream this should also be possible to expose the same API - a typed stream of events.
|
||||
|
|
|
@ -5,7 +5,7 @@ title: Actor API
|
|||
# UntypedActor API
|
||||
The `UntypedActor` class defines only one abstract method, the above mentioned `OnReceive(object message)`, which implements the behavior of the actor.
|
||||
|
||||
If the current actor behavior does not match a received message, it's recommended that you call the unhandled method, which by default publishes a new `Akka.Actor.UnhandledMessage(message, sender, recipient)` on the actor system’s event stream (set configuration item `Unhandled` to on to have them converted into actual `Debug` messages).
|
||||
If the current actor behavior does not match a received message, it's recommended that you call the unhandled method, which by default publishes a new `Akka.Actor.UnhandledMessage(message, sender, recipient)` on the actor system's event stream (set configuration item `Unhandled` to on to have them converted into actual `Debug` messages).
|
||||
|
||||
In addition, it offers:
|
||||
|
||||
|
@ -15,7 +15,7 @@ In addition, it offers:
|
|||
|
||||
* `SupervisorStrategy` user overridable definition the strategy to use for supervising child actors
|
||||
|
||||
This strategy is typically declared inside the actor in order to have access to the actor’s internal state within the decider function: since failure is communicated as a message sent to the supervisor and processed like other messages (albeit outside of the normal behavior), all values and variables within the actor are available, as is the `Sender` reference (which will be the immediate child reporting the failure; if the original failure occurred within a distant descendant it is still reported one level up at a time).
|
||||
This strategy is typically declared inside the actor in order to have access to the actor's internal state within the decider function: since failure is communicated as a message sent to the supervisor and processed like other messages (albeit outside of the normal behavior), all values and variables within the actor are available, as is the `Sender` reference (which will be the immediate child reporting the failure; if the original failure occurred within a distant descendant it is still reported one level up at a time).
|
||||
|
||||
* `Context` exposes contextual information for the actor and the current message, such as:
|
||||
|
||||
|
@ -102,7 +102,7 @@ It should be noted that the `Terminated` message is generated independent of the
|
|||
|
||||
Registering multiple times does not necessarily lead to multiple messages being generated, but there is no guarantee that only exactly one such message is received: if termination of the watched actor has generated and queued the message, and another registration is done before this message has been processed, then a second message will be queued, because registering for monitoring of an already terminated actor leads to the immediate generation of the `Terminated` message.
|
||||
|
||||
It is also possible to deregister from watching another actor’s liveliness using `Context.Unwatch(target)`. This works even if the Terminated message has already been enqueued in the mailbox; after calling unwatch no `Terminated` message for that actor will be processed anymore.
|
||||
It is also possible to deregister from watching another actor's liveliness using `Context.Unwatch(target)`. This works even if the Terminated message has already been enqueued in the mailbox; after calling unwatch no `Terminated` message for that actor will be processed anymore.
|
||||
|
||||
## Start Hook
|
||||
Right after starting the actor, its `PreStart` method is invoked.
|
||||
|
@ -114,15 +114,15 @@ protected override void PreStart()
|
|||
}
|
||||
```
|
||||
|
||||
This method is called when the actor is first created. During restarts it is called by the default implementation of `PostRestart`, which means that by overriding that method you can choose whether the initialization code in this method is called only exactly once for this actor or for every restart. Initialization code which is part of the actor’s constructor will always be called when an instance of the actor class is created, which happens at every restart.
|
||||
This method is called when the actor is first created. During restarts it is called by the default implementation of `PostRestart`, which means that by overriding that method you can choose whether the initialization code in this method is called only exactly once for this actor or for every restart. Initialization code which is part of the actor's constructor will always be called when an instance of the actor class is created, which happens at every restart.
|
||||
|
||||
## Restart Hooks
|
||||
All actors are supervised, i.e. linked to another actor with a fault handling strategy. Actors may be restarted in case an exception is thrown while processing a message (see [Supervision and Monitoring](supervision-and-monitoring). This restart involves the hooks mentioned above:
|
||||
|
||||
- The old actor is informed by calling `PreRestart` with the exception which caused the restart and the message which triggered that exception; the latter may be None if the restart was not caused by processing a message, e.g. when a supervisor does not trap the exception and is restarted in turn by its supervisor, or if an actor is restarted due to a sibling’s failure. If the message is available, then that message’s sender is also accessible in the usual way (i.e. by calling the `Sender` property).
|
||||
- The old actor is informed by calling `PreRestart` with the exception which caused the restart and the message which triggered that exception; the latter may be None if the restart was not caused by processing a message, e.g. when a supervisor does not trap the exception and is restarted in turn by its supervisor, or if an actor is restarted due to a sibling's failure. If the message is available, then that message's sender is also accessible in the usual way (i.e. by calling the `Sender` property).
|
||||
This method is the best place for cleaning up, preparing hand-over to the fresh actor instance, etc. By default it stops all children and calls `PostStop`.
|
||||
- The initial factory from the `ActorOf` call is used to produce the fresh instance.
|
||||
- The new actor’s `PostRestart` method is invoked with the exception which caused the restart. By default the `PreStart` is called, just as in the normal start-up case.
|
||||
- The new actor's `PostRestart` method is invoked with the exception which caused the restart. By default the `PreStart` is called, just as in the normal start-up case.
|
||||
|
||||
An actor restart replaces only the actual actor object; the contents of the mailbox is unaffected by the restart, so processing of messages will resume after the `PostRestart` hook returns. The message that triggered the exception will not be received again. Any message sent to an actor while it is being restarted will be queued to its mailbox as usual.
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ ActorSystem system = ActorSystem.Create("MySystem");
|
|||
IActorRef myActor = system.ActorOf(Props.Create(typeof(MyActor)), "myactor");
|
||||
```
|
||||
|
||||
Using the `ActorSystem` will create top-level actors, supervised by the actor system’s provided guardian actor, while using an actor’s context will create a child actor.
|
||||
Using the `ActorSystem` will create top-level actors, supervised by the actor system's provided guardian actor, while using an actor's context will create a child actor.
|
||||
|
||||
```csharp
|
||||
public class FirstActor : ReceiveActor
|
||||
|
@ -114,7 +114,7 @@ The name parameter is optional, but you should preferably name your actors, sinc
|
|||
Actors are automatically started asynchronously when created.
|
||||
|
||||
## The Inbox
|
||||
When writing code outside of actors which shall communicate with actors, the ask pattern can be a solution (see below), but there are two things it cannot do: receiving multiple replies (e.g. by subscribing an `IActorRef` to a notification service) and watching other actors’ lifecycle. For these purposes there is the `Inbox` class:
|
||||
When writing code outside of actors which shall communicate with actors, the ask pattern can be a solution (see below), but there are two things it cannot do: receiving multiple replies (e.g. by subscribing an `IActorRef` to a notification service) and watching other actors' lifecycle. For these purposes there is the `Inbox` class:
|
||||
```csharp
|
||||
var target = system.ActorOf(Props.Empty);
|
||||
var inbox = Inbox.Create(system);
|
||||
|
@ -131,7 +131,7 @@ catch (TimeoutException)
|
|||
}
|
||||
```
|
||||
|
||||
The send method wraps a normal `Tell` and supplies the internal actor’s reference as the sender. This allows the reply to be received on the last line. Watching an actor is quite simple as well
|
||||
The send method wraps a normal `Tell` and supplies the internal actor's reference as the sender. This allows the reply to be received on the last line. Watching an actor is quite simple as well
|
||||
```csharp
|
||||
using System.Diagnostics;
|
||||
...
|
||||
|
|
|
@ -5,7 +5,7 @@ title: Sending messages
|
|||
# Sending messages
|
||||
|
||||
## Messages and immutability
|
||||
**IMPORTANT:** Messages can be any kind of object but have to be immutable. Akka can’t enforce immutability (yet) so this has to be by convention.
|
||||
**IMPORTANT:** Messages can be any kind of object but have to be immutable. Akka can't enforce immutability (yet) so this has to be by convention.
|
||||
|
||||
Here is an example of an immutable message:
|
||||
|
||||
|
@ -40,7 +40,7 @@ In all these methods you have the option of passing along your own ActorRef. Mak
|
|||
This is the preferred way of sending messages. No blocking waiting for a message. This gives the best concurrency and scalability characteristics.
|
||||
|
||||
```csharp
|
||||
// don’t forget to think about who is the sender (2nd argument)
|
||||
// don't forget to think about who is the sender (2nd argument)
|
||||
target.Tell(message, Self);
|
||||
```
|
||||
The sender reference is passed along with the message and available within the receiving actor via its Sender property while processing this message. Inside of an actor it is usually Self who shall be the sender, but there can be cases where replies shall be routed to some other actor—e.g. the parent—in which the second argument to tell would be a different one. Outside of an actor and if no reply is needed the second argument can be null; if a reply is needed outside of an actor you can use the ask-pattern described next.
|
||||
|
@ -87,7 +87,7 @@ If the actor does not complete the task, it will expire after the timeout period
|
|||
For more information on Tasks, check out the [MSDN documentation](https://msdn.microsoft.com/en-us/library/dd537609(v=vs.110).aspx).
|
||||
|
||||
>**Warning**<br/>
|
||||
When using task callbacks inside actors, you need to carefully avoid closing over the containing actor’s reference, i.e. do not call methods or access mutable state on the enclosing actor from within the callback. This would break the actor encapsulation and may introduce synchronization bugs and race conditions because the callback will be scheduled concurrently to the enclosing actor. Unfortunately there is not yet a way to detect these illegal accesses at compile time. See also: [[Actors and shared mutable state]]
|
||||
When using task callbacks inside actors, you need to carefully avoid closing over the containing actor's reference, i.e. do not call methods or access mutable state on the enclosing actor from within the callback. This would break the actor encapsulation and may introduce synchronization bugs and race conditions because the callback will be scheduled concurrently to the enclosing actor. Unfortunately there is not yet a way to detect these illegal accesses at compile time. See also: [[Actors and shared mutable state]]
|
||||
|
||||
### Forward message
|
||||
You can forward a message from one actor to another. This means that the original sender address/reference is maintained even though the message is going through a 'mediator'. This can be useful when writing actors that work as routers, load-balancers, replicators etc. You need to pass along your context variable as well.
|
||||
|
|
Загрузка…
Ссылка в новой задаче