Skip to content

Commit

Permalink
Merge pull request #3738 from akkadotnet/dev
Browse files Browse the repository at this point in the history
v1.3.12 Production Release
  • Loading branch information
Aaronontheweb authored Mar 14, 2019
2 parents f7d5b6e + 49e0612 commit 8a8cbe7
Show file tree
Hide file tree
Showing 52 changed files with 2,050 additions and 466 deletions.
30 changes: 30 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
#### 1.3.12 March 13 2019 ####
**Maintenance Release for Akka.NET 1.3**
This will be the final bugfix release for Akka.NET v1.3.* - going forward we will be working on releasing Akka.NET v1.4.

This patch contains many important bug fixes and improvements:
* [Akka.Cluster.Sharding: Automatic passivation for sharding](https://github.com/akkadotnet/akka.net/pull/3718)
* [Akka.Persistence: Optimize AtLeastOnceDelivery by not scheduling ticks when not needed](https://github.com/akkadotnet/akka.net/pull/3704)
* [Akka.Persistence.Sql.Common: Bugfix CurrentEventsByTag does not return more than a 100 events](https://github.com/akkadotnet/akka.net/issues/3697)
* [Akka.Persistence.Sql.Common: DeleteMessages when journal is empty causes duplicate key SQL exception](https://github.com/akkadotnet/akka.net/issues/3721)
* [Akka.Cluster: SplitBrainResolver: don't down oldest if alone in cluster](https://github.com/akkadotnet/akka.net/pull/3690)
* [Akka: Include manifest or class in missing serializer failure if possible](https://github.com/akkadotnet/akka.net/pull/3701)
* [Akka: Memory leak when disposing actor system with non default ActorRefProvider](https://github.com/akkadotnet/akka.net/issues/2640)

To [see the full set of changes for Akka.NET v1.3.12, click here](https://github.com/akkadotnet/akka.net/milestone/30).

| COMMITS | LOC+ | LOC- | AUTHOR |
| --- | --- | --- | --- |
| 8 | 1487 | 357 | Ismael Hamed |
| 7 | 126 | 120 | jdsartori |
| 3 | 198 | 4 | JSartori |
| 3 | 155 | 22 | Aaron Stannard |
| 2 | 11 | 2 | Peter Lin |
| 1 | 8 | 4 | Raimund Hirz |
| 1 | 7 | 0 | Warren Falk |
| 1 | 45 | 6 | Peter Huang |
| 1 | 14 | 13 | Bartosz Sypytkowski |
| 1 | 11 | 1 | Greg Shackles |
| 1 | 10 | 10 | Jill D. Headen |
| 1 | 1 | 1 | Isaac Z |

#### 1.3.11 December 17 2018 ####
**Maintenance Release for Akka.NET 1.3**

Expand Down
4 changes: 2 additions & 2 deletions docs/articles/actors/coordinated-shutdown.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ The default phases are defined in a linear order, but in practice the phases are

## Registering Tasks to a Phase

For instance, if you're using [Akka.Cluster](../clustering/cluster-overview) it's commonplace to register application-specific cleanup tasks during the `cluster-leave` and `cluster-exiting` phases. Here's an example:
For instance, if you're using [Akka.Cluster](../clustering/cluster-overview.md) it's commonplace to register application-specific cleanup tasks during the `cluster-leave` and `cluster-exiting` phases. Here's an example:

```
var coordShutdown = CoordinatedShutdown.Get(myActorSystem);
Expand Down Expand Up @@ -163,4 +163,4 @@ If you wish to disable this behavior, you can pass in the following HOCON config

```
akka.coordinated-shutdown.run-by-clr-shutdown-hook = off
```
```
192 changes: 192 additions & 0 deletions docs/articles/actors/di-core.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
---
uid: di-core
title: DI Core
---

# Akka.DI.Core

**Actor Producer Extension** library is used to create a Dependency Injection Container for the [Akka.NET](https://github.com/akkadotnet/akka.net) framework.

# What is it?

**Akka.DI.Core** is an **ActorSystem extension** library for the Akka.NET
framework that provides a simple way to create an Actor Dependency Resolver
that can be used an alternative to the basic capabilities of [Props](Props)
when you have actors with multiple dependencies.

# How do you create an Extension?

- Create a new class library
- Reference your favorite IoC Container, the Akka.DI.Core, and of course Akka
- Create a class and implement the `IDependencyResolver`

Let's walk through the process of creating one for the CastleWindsor container.
You need to create a new project named Akka.DI.CastleWindsor with all the necessary references including Akka.DI.Core, Akka, and CastleWindosor.
Name the initial class `WindsorDependencyResolver`.

```csharp
public class WindsorDependencyResolver : IDependencyResolver
{
// we'll implement IDependencyResolver in the following steps
}
```

Add a constructor and private fields.

```csharp
private IWindsorContainer _container;
private ConcurrentDictionary<string, Type> _typeCache;
private ActorSystem _system;

public WindsorDependencyResolver(IWindsorContainer container, ActorSystem system)
{
if (system == null) throw new ArgumentNullException("system");
if (container == null) throw new ArgumentNullException("container");
_container = container;
_typeCache = new ConcurrentDictionary<string, Type>(StringComparer.InvariantCultureIgnoreCase);
_system = system;
_system.AddDependencyResolver(this);
}
```

You have defined three private fields

- ```IWindsorContainer _container``` is a reference to the CastleWindsor container.
- ```ConcurrentDictionary<string, Type> _typeCache``` is a thread safe map that contains actor name/type associations.
- ```ActorSystem _system``` is a reference to the ActorSystem.

First you need to implement ```GetType```. This is a basic implementation and
is just for demonstration purposes. Essentially this is used by the extension
to get the type of the actor from it's type name.

```csharp
public Type GetType(string actorName)
{
_typeCache.
TryAdd(actorName,
actorName.GetTypeValue() ??
_container.Kernel
.GetAssignableHandlers(typeof(object))
.Where(handler => handler.ComponentModel.Name.Equals(actorName, StringComparison.InvariantCultureIgnoreCase))
.Select(handler => handler.ComponentModel.Implementation)
.FirstOrDefault());

return _typeCache[actorName];
}
```

Secondly you need to implement the ```CreateActorFactory``` method which will be
used by the extension to create the actor. This implementation will depend upon
the API of the container.

```csharp
public Func<ActorBase> CreateActorFactory(Type actorType)
{
return () => (ActorBase)container.Resolve(actorType);
}
```

Thirdly, you implement the ```Create<TActor>``` which is used register the
`Props` configuration for the referenced actor type with the `ActorSystem`.
This method will always be the same implementation.

```csharp
public Props Create<TActor>() where TActor : ActorBase
{
return system.GetExtension<DIExt>().Props(typeof(TActor).Name);
}
```

Lastly, you implement the Release method which, in this instance, is very simple.
This method is used to remove the actor from the underlying container.

```csharp
public void Release(ActorBase actor)
{
this.container.Release(actor);
}
```

**Note: For further details on the importance of the release method please read
the following blog [post](http://blog.ploeh.dk/2014/05/19/di-friendly-framework/).**

The resulting class should look similar to the following:

```csharp
public class WindsorDependencyResolver : IDependencyResolver
{
private IWindsorContainer container;
private ConcurrentDictionary<string, Type> typeCache;
private ActorSystem system;

public WindsorDependencyResolver(IWindsorContainer container, ActorSystem system)
{
if (system == null) throw new ArgumentNullException("system");
if (container == null) throw new ArgumentNullException("container");
this.container = container;
typeCache = new ConcurrentDictionary<string, Type>(StringComparer.InvariantCultureIgnoreCase);
this.system = system;
this.system.AddDependencyResolver(this);
}

public Type GetType(string actorName)
{
typeCache.TryAdd(actorName, actorName.GetTypeValue() ??
container.Kernel
.GetAssignableHandlers(typeof(object))
.Where(handler => handler.ComponentModel.Name.Equals(actorName, StringComparison.InvariantCultureIgnoreCase))
.Select(handler => handler.ComponentModel.Implementation)
.FirstOrDefault());

return typeCache[actorName];
}

public Func<ActorBase> CreateActorFactory(Type actorType)
{
return () => (ActorBase)container.Resolve(actorType);
}

public Props Create<TActor>() where TActor : ActorBase
{
return system.GetExtension<DIExt>().Props(typeof(TActor));
}

public void Release(ActorBase actor)
{
this.container.Release(actor);
}
}
```

Now, with the preceding class, you can do something like the following example:

```csharp
// Setup CastleWindsor
IWindsorContainer container = new WindsorContainer();
container.Register(Component.For<IWorkerService>().ImplementedBy<WorkerService>());
container.Register(Component.For<TypedWorker>().Named("TypedWorker").LifestyleTransient());

// Create the ActorSystem
using (var system = ActorSystem.Create("MySystem"))
{
// Create the dependency resolver
IDependencyResolver resolver = new WindsorDependencyResolver(container, system);

// Register the actors with the system
system.ActorOf(system.DI().Props<TypedWorker>(), "Worker1");
system.ActorOf(system.DI().Props<TypedWorker>(), "Worker2");

// Create the router
IActorRef router = system.ActorOf(Props.Empty.WithRouter(new ConsistentHashingGroup(config)));

// Create the message to send
TypedActorMessage message = new TypedActorMessage
{
Id = 1,
Name = Guid.NewGuid().ToString()
};

// Send the message to the router
router.Tell(message);
}
```
6 changes: 5 additions & 1 deletion docs/articles/clustering/cluster-sharding.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,11 @@ By default rebalancing process always happens from nodes with the highest number

## Passivation

To reduce memory consumption, you may decide to stop entities after some period of inactivity using `Context.SetReceiveTimeout(timeout)`. In order to make cluster sharding aware of stopping entities, **DON'T use `Context.Stop(Self)` on the entities**, as this may result in losing messages. Instead send a `Passivate` message message to current entity `Context.Parent` (which is shard itself in this case). This will inform shard to stop forwarding messages to target entity, and buffer them instead until it's terminated. Once that happens, if there are still some messages buffered, entity will be reincarnated and messages flushed to it automatically.
To reduce memory consumption, you may decide to stop entities after some period of inactivity using `Context.SetReceiveTimeout(timeout)`. In order to make cluster sharding aware of stopping entities, **DON'T use `Context.Stop(Self)` on the entities**, as this may result in losing messages. Instead send a `ShardRegion.Passivate` message to current entity `Context.Parent` (which is shard itself in this case). This will inform shard to stop forwarding messages to target entity, and buffer them instead until it's terminated. Once that happens, if there are still some messages buffered, entity will be reincarnated and messages flushed to it automatically.

### Automatic Passivation

The entities can be configured to be automatically passivated if they haven't received a message for a while using the `akka.cluster.sharding.passivate-idle-entity-after` setting, or by explicitly setting `ClusterShardingSettings.passivateIdleEntityAfter` to a suitable time to keep the actor alive. Note that only messages sent through sharding are counted, so direct messages to the `ActorRef` of the actor or messages that it sends to itself are not counted as activity. By default automatic passivation is disabled.

## Remembering entities

Expand Down
12 changes: 7 additions & 5 deletions docs/articles/concepts/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ title: Configuration
Akka.NET leverages a configuration format, called HOCON, to allow you to configure your Akka.NET applications with whatever level of granularity you want.

#### What is HOCON?
HOCON (Human-Optimized Config Object Notation) is a flexible and extensible configuration format. It will allow you to configure everything from Akka.NET's `IActorRefProvider` implementation, logging, network transports, and more commonly - how individual actors are deployed.
HOCON (Human-Optimized Config Object Notation) is a flexible and extensible configuration format.
It allows you to configure everything from Akka.NET's `IActorRefProvider` implementation: logging, network transports, and (more commonly) how individual actors are deployed.

Values returned by HOCON are strongly typed (i.e. you can fetch out an `int`, a `Timespan`, etc).
Values returned by HOCON are strongly typed, which means you can fetch out an `int`, a `Timespan`, etc.

#### What can I do with HOCON?
HOCON allows you to embed easily-readable configuration inside of the otherwise hard-to-read XML in App.config and Web.config. HOCON also lets you query configs by their section paths, and those sections are exposed strongly typed and parsed values you can use inside your applications.
HOCON allows you to embed easy-to-read configuration inside of the otherwise hard-to-read XML in App.config and Web.config.
HOCON also lets you query configs by their section paths, and those sections are exposed strongly typed and parsed values you can use inside your applications.

HOCON also lets you nest and/or chain sections of configuration, creating layers of granularity and providing you a semantically namespaced config.

Expand Down Expand Up @@ -43,7 +45,7 @@ Deployment is a vague concept, but it's closely tied to HOCON. An actor is "depl

When an actor is instantiated within the `ActorSystem` it can be deployed in one of two places: inside the local process or in another process (this is what `Akka.Remote` does.)

When an actor is deployed by the `ActorSystem`, it has a range of configuration settings. These settings control a wide range of behavior options for the actor, such as: is this actor going to be a router? What `Dispatcher` will it use? What type of mailbox will it have? (More on these concepts in later lessons.)
When an actor is deployed by the `ActorSystem`, it has a range of configuration settings. These settings control a wide range of behavior options for the actor such as: is this actor going to be a router? What `Dispatcher` will it use? What type of mailbox will it have? (More on these concepts in later lessons.)

We haven't gone over what all these options mean, but *the key thing to know for now is that the settings used by the `ActorSystem` to deploy an actor into service can be set within HOCON. *

Expand Down Expand Up @@ -147,4 +149,4 @@ var c = yourConfig.GetString("c");

![Fallback HOCON Config Behavior](/images/hocon-config-fallbacks.gif)

In this case `yourConfig` will fallback twice to `f2` and return "baz" as the value for key `c`.
In this case `yourConfig` will fallback twice to `f2` and return "baz" as the value for key `c`.
Loading

0 comments on commit 8a8cbe7

Please sign in to comment.