Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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