Skip to content

Commit

Permalink
close akkadotnet#4096 - documented how to terminate remembered entities
Browse files Browse the repository at this point in the history
Updated the Akka.Cluster.Sharding documentation to explain how to terminate remembered-entities.
  • Loading branch information
Aaronontheweb committed Apr 9, 2021
1 parent 56cae11 commit 471e270
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
37 changes: 37 additions & 0 deletions docs/articles/clustering/cluster-sharding.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,43 @@ public sealed class MessageExtractor : HashCodeMessageExtractor

Using `ShardRegion.StartEntity` implies, that you're able to infer a shard id given an entity id alone. For this reason, in example above we modified a cluster sharding routing logic to make use of `HashCodeMessageExtractor` - in this variant, shard id doesn't have to be provided explicitly, as it will be computed from the hash of entity id itself. Notice a `maxNumberOfShards`, which is the maximum available number of shards allowed for this type of an actor - this value must never change during a single lifetime of a cluster.

### Terminating remembered entities
One complication that `akka.cluster.sharding.remember-entities = true` introduces is that your sharded entity actors can no longer be terminated through the normal Akka.NET channels, i.e. `Context.Stop(Self)`, `PoisonPill.Instance`, and the like. This is because as part of the `remember-entities` contract - the sharding system is going to insist on keeping all remembered entities alive until explictily told to stop.

To terminate a remembered entity, the sharded entity actor needs to send a [`Passivate` command](xref:Akka.Cluster.Sharding.Passivate) _to its parent actor_ in order to signal to the sharding system that we no longer need to remember this particular entity.

```csharp
protected override bool ReceiveCommand(object message)
{
switch (message)
{
case Increment _:
Persist(new CounterChanged(1), UpdateState);
return true;
case Decrement _:
Persist(new CounterChanged(-1), UpdateState);
return true;
case Get _:
Sender.Tell(_count);
return true;
case ReceiveTimeout _:
// send Passivate to parent (shard actor) to stop remembering this entity.
// shard actor will send us back a `Stop.Instance` message
// as our "shutdown" signal - at which point we can terminate normally.
Context.Parent.Tell(new Passivate(Stop.Instance));
return true;
case Stop _:
Context.Stop(Self);
return true;
}
return false;
}
```

It is common to simply use `Context.Parent.Tell(new Passivate(PoisonPill.Instance));` to passivate and shutdown remembered-entity actors.

To recreate a remembered entity actor after it has been passivated all you have to do is message the `ShardRegion` actor with a message containing the entity's `EntityId` again just like how you instantiated the actor the first time.

## Retrieving sharding state

You can inspect current sharding stats by using following messages:
Expand Down
4 changes: 2 additions & 2 deletions src/contrib/cluster/Akka.Cluster.Sharding/ShardingMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ private Terminate()
/// reduce memory consumption. This is done by the application specific implementation of
/// the entity actors for example by defining receive timeout (<see cref="IActorContext.SetReceiveTimeout"/>).
/// If a message is already enqueued to the entity when it stops itself the enqueued message
/// in the mailbox will be dropped. To support graceful passivation without loosing such
/// in the mailbox will be dropped. To support graceful passivation without losing such
/// messages the entity actor can send this <see cref="Passivate"/> message to its parent <see cref="ShardRegion"/>.
/// The specified wrapped <see cref="StopMessage"/> will be sent back to the entity, which is
/// then supposed to stop itself. Incoming messages will be buffered by the `ShardRegion`
/// between reception of <see cref="Passivate"/> and termination of the entity. Such buffered messages
/// are thereafter delivered to a new incarnation of the entity.
///
/// <see cref="PoisonPill"/> is a perfectly fine <see cref="StopMessage"/>.
/// <see cref="PoisonPill.Instance"/> is a perfectly fine <see cref="StopMessage"/>.
/// </summary>
[Serializable]
public sealed class Passivate : IShardRegionCommand
Expand Down

0 comments on commit 471e270

Please sign in to comment.