Skip to content

Commit

Permalink
Merge pull request #4526 from akkadotnet/dev
Browse files Browse the repository at this point in the history
v1.4.9 Stable Release
  • Loading branch information
Aaronontheweb authored Jul 21, 2020
2 parents aedb9c6 + b9237f9 commit e5f400d
Show file tree
Hide file tree
Showing 73 changed files with 1,546 additions and 132 deletions.
25 changes: 25 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
#### 1.4.9 July 21 2020 ####
**Maintenance Release for Akka.NET 1.4**

Akka.NET v1.4.9 features some important bug fixes for Akka.NET v1.4:

* [Akka: Re-enable dead letter logging after specified duration](https://github.com/akkadotnet/akka.net/pull/4513)
* [Akka: Optimize allocations in `ActorPath.Join()`](https://github.com/akkadotnet/akka.net/pull/4510)
* [Akka.IO: Optimize TCP-related actor creation in Akka.IO](https://github.com/akkadotnet/akka.net/pull/4509)
* [Akka.DistributedData: Resolve "An Item with the same key but different value already exists" error during pruning](https://github.com/akkadotnet/akka.net/pull/4512)
* [Akka.Cluster: Cluster event listener that logs all events](https://github.com/akkadotnet/akka.net/pull/4502)
* [Akka.Cluster.Tools.Singleton.ClusterSingletonManager bug: An element with the same key but a different value already exists](https://github.com/akkadotnet/akka.net/issues/4474)

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

| COMMITS | LOC+ | LOC- | AUTHOR |
| --- | --- | --- | --- |
| 6 | 1008 | 90 | Gregorius Soedharmo |
| 5 | 475 | 27 | Ismael Hamed |
| 3 | 6 | 6 | dependabot-preview[bot] |
| 2 | 28 | 5 | Petri Kero |
| 1 | 3 | 0 | Aaron Stannard |
| 1 | 2 | 2 | tometchy |
| 1 | 1 | 1 | to11mtm |
| 1 | 1 | 1 | Kevin Preller |

#### 1.4.8 June 17 2020 ####
**Maintenance Release for Akka.NET 1.4**

Expand Down
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ NUGET_URL=https://dist.nuget.org/win-x86-commandline/v4.3.0/nuget.exe
FAKE_VERSION=4.63.0
FAKE_EXE=$TOOLS_DIR/FAKE/tools/FAKE.exe
DOTNET_EXE=$SCRIPT_DIR/.dotnet/dotnet
DOTNET_VERSION=3.1.100
DOTNET_VERSION=3.1.105
DOTNET_INSTALLER_URL=https://dot.net/v1/dotnet-install.sh
DOTNET_CHANNEL=LTS
PROTOBUF_VERSION=3.4.0
Expand Down
15 changes: 8 additions & 7 deletions docs/articles/actors/finite-state-machine.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ using Akka.Event;

The contract of our `Buncher` actor is that it accepts or produces the following messages:

[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/FiniteStateMachine.Messages.cs#L16-L50)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/FiniteStateMachine.Messages.cs?name=FSMEvents)]

`SetTarget` is needed for starting it up, setting the destination for the Batches to be passed on; `Queue` will add to the internal queue while `Flush` will mark the end of a burst.

[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/FiniteStateMachine.Messages.cs#L52-L86)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/FiniteStateMachine.Messages.cs?name=FSMData)]

The actor can be in two states: no message queued (aka `Idle`) or some message queued (aka `Active`). It will stay in the active state as long as messages keep arriving and no flush is requested. The internal state data of the actor is made up of the target actor reference to send the batches to and the actual queue of messages.

[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/ExampleFSMActor.cs?range=8-42,72-75)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/ExampleFSMActor.cs?name=FSMActorStart)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/ExampleFSMActor.cs?name=FSMActorEnd)]

The basic strategy is to declare the actor, inherit from `FSM` class and specifying the possible states and data values as type parameters. Within the body of the actor a DSL is used for declaring the state machine:

Expand All @@ -34,19 +35,19 @@ The basic strategy is to declare the actor, inherit from `FSM` class and specify

In this case, we start out in the `Idle` and `Uninitialized` state, where only the `SetTarget()` message is handled; stay prepares to end this event’s processing for not leaving the current state, while the using modifier makes the `FSM` replace the internal state (which is `Uninitialized` at this point) with a fresh `Todo()` object containing the target actor reference. The `Active` state has a state timeout declared, which means that if no message is received for 1 second, a `FSM.StateTimeout` message will be generated. This has the same effect as receiving the `Flush` command in this case, namely to transition back into the Idle state and resetting the internal queue to the empty vector. But how do messages get queued? Since this shall work identically in both states, we make use of the fact that any event which is not handled by the `When()` block is passed to the `WhenUnhandled()` block:

[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/ExampleFSMActor.cs?range=44-55)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/ExampleFSMActor.cs?name=UnhandledHandler)]

The first case handled here is adding `Queue()` requests to the internal queue and going to the `Active` state (this does the obvious thing of staying in the `Active` state if already there), but only if the `FSM` data are not `Uninitialized` when the `Queue()` event is received. Otherwise—and in all other non-handled cases—the second case just logs a warning and does not change the internal state.

The only missing piece is where the `Batches` are actually sent to the target, for which we use the `OnTransition` mechanism: you can declare multiple such blocks and all of them will be tried for matching behavior in case a state transition occurs (i.e. only when the state actually changes).

[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/ExampleFSMActor.cs?range=57-70)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/ExampleFSMActor.cs?name=TransitionHandler)]

The transition callback is a function which takes as input a pair of states—the current and the next state. The `FSM` class includes a convenience extractor for these in form of an arrow operator, which conveniently reminds you of the direction of the state change which is being matched. During the state change, the old state data is available via `StateData` as shown, and the new state data would be available as `NextStateData`.

To verify that this buncher actually works, it is quite easy to write a test using the `Testing Actor Systems`.

[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/ExampleFSMActorTests.cs?range=9-33)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/ExampleFSMActorTests.cs?name=FSMTest)]

## Reference

Expand Down Expand Up @@ -86,7 +87,7 @@ If the `timeout` parameter is given, then all transitions into this state, inclu

The `stateFunction` argument is a `delegate State<TState, TData> StateFunction(Event<TData> fsmEvent)`.

[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/ExampleFSMActor.cs?range=16-35)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/FiniteStateMachine/ExampleFSMActor.cs?name=FSMHandlers)]

### Defining the Initial State
Each `FSM` needs a starting point, which is declared using
Expand Down
2 changes: 1 addition & 1 deletion docs/articles/actors/untyped-actor-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ Messages can be sent via the `ActorSelection` and the path of the `ActorSelectio

To acquire an `IActorRef` for an `ActorSelection` you need to send a message to the selection and use the `Sender` reference of the reply from the actor. There is a built-in `Identify` message that all Actors will understand and automatically reply to with a `ActorIdentity` message containing the `IActorRef`. This message is handled specially by the actors which are traversed in the sense that if a concrete name lookup fails (i.e. a non-wildcard path element does not correspond to a live actor) then a negative result is generated. Please note that this does not mean that delivery of that reply is guaranteed, it still is a normal message.

[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/UntypedActorAPI/Follower.cs?range=8-41)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Actors/UntypedActorAPI/Follower.cs?name=UntypedActor)]

You can also acquire an `IActorRef` for an `ActorSelection` with the `ResolveOne` method of the `ActorSelection`. It returns a Task of the matching `IActorRef` if such an actor exists. It is completed with failure `akka.actor.ActorNotFound` if no such actor exists or the identification didn't complete within the supplied timeout.

Expand Down
4 changes: 2 additions & 2 deletions docs/articles/clustering/cluster-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,11 @@ akka.extensions = ["Akka.Cluster.Tools.Client.ClusterClientReceptionistExtension
## Events
As mentioned earlier, both the `ClusterClient` and `ClusterClientReceptionist` emit events that can be subscribed to. The following code snippet declares an actor that will receive notifications on contact points (addresses to the available receptionists), as they become available. The code illustrates subscribing to the events and receiving the `ClusterClient` initial state.

[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Networking/ClusterClient/ClientListener.cs?range=7-47)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Networking/ClusterClient/ClientListener.cs?name=ClusterClient)]

Similarly we can have an actor that behaves in a similar fashion for learning what cluster clients contact a `ClusterClientReceptionist`:

[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Networking/ClusterClient/ReceptionistListener.cs?range=7-47)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Networking/ClusterClient/ReceptionistListener.cs?name=ReceptionistListener)]

## Configuration
The `ClusterClientReceptionist` extension (or `ClusterReceptionistSettings`) can be configured with the following properties:
Expand Down
14 changes: 14 additions & 0 deletions docs/articles/clustering/cluster-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ akka {
}
```

### Cluster Info Logging

You can silence the logging of cluster events at info level with configuration property:

```
akka.cluster.log-info = off
```

You can enable verbose logging of cluster events at info level, e.g. for temporary troubleshooting, with configuration property:

```
akka.cluster.log-info-verbose = on
```

## Specifying Minimum Cluster Sizes
One feature of Akka.Cluster that can be useful in a number of scenarios is the ability to specify a minimum cluster size, i.e. "this cluster must have at least 3 nodes present before it can be considered 'up'."

Expand Down
4 changes: 2 additions & 2 deletions docs/articles/configuration/akka.streams.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ title: Akka.Streams Configuration
---

## Akka.Streams Configuration
Below is the default HOCON configuration for the base `Akka.Steams` package.
Below is the default HOCON configuration for the base `Akka.Streams` package.

[!code[Akka.Streams.dll HOCON Configuration](../../../src/core/Akka.Streams/reference.conf)]
[!code[Akka.Streams.dll HOCON Configuration](../../../src/core/Akka.Streams/reference.conf)]
4 changes: 2 additions & 2 deletions docs/articles/networking/serialization.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ So, to create a custom serializer, all that is needed is a class that inherits f
### Creating new Serializers
A custom `Serializer` has to inherit from `Akka.Serialization.Serializer` and can be defined like this:

[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Networking/Serialization/CreateCustomSerializer.cs?range=7-42)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Networking/Serialization/CreateCustomSerializer.cs?name=CustomSerialization)]

The only thing left to do for this class would be to fill in the serialization logic in the ``ToBinary(object)`` method and the deserialization logic in the ``FromBinary(byte[], Type)``.
Afterwards the configuration would need to be updated to reflect which name to bind to and the classes that use this
Expand All @@ -142,7 +142,7 @@ The manifest string can also encode a version number that can be used in `FromBi
If the data was originally serialized with `Serializer`, and in a later version of the system you change to `SerializerWithStringManifest`, the manifest string will be the full class name if you used `IncludeManifest=true`, otherwise it will be the empty string.

This is how a `SerializerWithStringManifest` looks:
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Networking/Serialization/MyOwnSerializer2.cs?range=9-66)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Networking/Serialization/MyOwnSerializer2.cs?name=CustomSerialization)]

You must also bind it to a name in your `Configuration` and then list which classes that should be serialized using it.

Expand Down
4 changes: 2 additions & 2 deletions docs/articles/persistence/at-least-once-delivery.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ If the persistent actor is not currently recovering, the deliver method will sen

Deliver requires a `deliveryMessageMapper` function to pass the provided `deliveryId` into the message so that the correlation between `Deliver` and `ConfirmDelivery` is possible. The `deliveryId` must do the round trip. Upon receipt of the message, the destination actor will send the same `deliveryId` wrapped in a confirmation message back to the sender. The sender will then use it to call the `ConfirmDelivery` method to complete the delivery routine.

[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Persistence/AtLeastOnceDelivery/AtLeastOnceDeliveryActor.Messages.cs?range=3-49)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Persistence/AtLeastOnceDelivery/AtLeastOnceDeliveryActor.Messages.cs?name=AtLeastOnceDelivery)]

[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Persistence/AtLeastOnceDelivery/ExampleAtLeastOnceDeliveryReceiveActor.cs?range=6-48)]
[!code-csharp[Main](../../../src/core/Akka.Docs.Tests/Persistence/AtLeastOnceDelivery/ExampleAtLeastOnceDeliveryReceiveActor.cs?name=AtLeastOnceDelivery)]

The `deliveryId` generated by the persistence module is a strictly monotonically increasing sequence number without gaps. The same sequence is used for all destinations of the actor, i.e. when sending to multiple destinations the destinations will see gaps in the sequence. It is not possible to use custom `deliveryId`. However, you can send a custom correlation identifier in the message to the destination. You must then retain a mapping between the internal `deliveryId` (passed into the `deliveryMessageMapper` function) and your custom correlation id (passed into the message). You can do this by storing such mapping in a Map(CorrelationId -> DeliveryId) from which you can retrieve the `deliveryId` to be passed into the `ConfirmDelivery` method once the receiver of your message has replied with your custom correlation id.

Expand Down
Loading

0 comments on commit e5f400d

Please sign in to comment.