Events
Events in the Hazelcast .NET Client rely on a handler-based model close to the C# event
model, though with a different syntax for adding and removing handlers, due to the asynchronous nature of these operations. Indeed, the following code has limitations:
thing.Updated += OnThingUpdated;
thing.Deleted += OnThingDeleted;
Here,
- The operations are distinct, whereas Hazelcast subscriptions can handle multiple events at once
- The subscription is synchronous, whereas Hazelcast needs to notify the members of the subscription
- The handlers (e.g.
OnThingUpdated
) are synchronous
Hazelcast Events
To overcome these limitations, the Hazelcast .NET Client uses the following syntax:
var id = await thing.SubscribeAsync(events => events
.Updated(OnThingUpdated)
.Deleted(OnThingDeleted));
Here, the handlers can be synchronous, for instance:
private void OnThingUpdated(Thing sender, ThingUpdatedEventArgs args)
{
...
}
But they can also be asynchronous, for instance:
private async ValueTask OnThingUpdated(Thing sender, ThingUpdatedEventArgs args)
{
await ...
}
In the example, the two events are subscribed at once and that subscription is represented by the returned id
, which is a Guid
. The two events can only be unsubscribed at once too, by passing this id
back to the UnsubscribeAsync
method:
await thing.UnsubscribeAsync(id);
Subscribing involves exchanging messages with the server, and takes time. Where traditional C# happily does:
thing.Updated += DoThis;
thing.Updated += AlsoDoThis;
It would be much more efficient to group the two handlers:
var id = await thing.SubscribeAsync(events => events
.Updated((sender, args) =>
{
DoThis(sender, args);
AlsoDoThis(sender, args);
}));
This is also the only way to guarantee the order of execution of the two handlers, as the order in which events trigger is not specified, and should not be relied upon.
Client Events
The IHazelcastClient exposes the following events:
StateChanged
triggers when the client state changesPartitionLost
triggers when a partition is lostPartitionsUpdated
triggers when the partitions table is updatedMembersUpdated
triggers when the members list is updatedObjectCreated
triggers when a distributed object is createdObjectDestroyed
triggers when a distributed object is destroyed
The IHazelcastClient directly supports subscribing to events. For instance:
var id = await client.SubscribeAsync(events => events
.StateChanged((sender, args) => {
System.Console.WriteLine($"New client state: {args.State}");
}));
StateChanged
The StateChanged
event triggers whenever the state of the client changes. Handles receive an instance of the StateChangedEventArgs class, which exposes the following property:
- State: the new ClientState
An IHazelcastClient instance goes through the following ClientState states:
- Starting: the client is starting and has not started to connect to members yet (transition state)
- Started: the client has started, and is now trying to connect to a first member (transition state)
- Connected: the client is connected to at least one member (operational state)
- Disconnected: the client has disconnected, due to its last member leaving the cluster, or a network error. Depending on its configuration it will either try to connect again (and transition back to Connected if successful) or fail and transition to Shutdown (transition state)
- ClusterChanged: the client switched the cluster, and connected.
Connected
state will be still reached afterClusterChanged
. It occurs only if failover happened. - ShuttingDown: the client has been disposed, i.e. properly requested to shut down, and is shutting down (transition state)
- Shutdown: the client has shut down (final state)
PartitionLost
The PartitionLost
event triggers whenever the server notifies the client that a partition has been lost, usually because a member carrying that partition has left the cluster. Handlers receive an instance of the PartitionLostEventArgs class, which exposes the following properties:
- PartitionId: the identifier of the lost partition
- LostBackupCount: how many backups were lost
- IsAllReplicasInPartitionLost: whether all replicas were lost
- Member: the member that was lost
PartitionsUpdated
The PartitionsUpdated
event triggers whenever the server notifies the client of a new partitions list. This happens when the partitions list changes, but also periodically when the server wants to ensure that clients are aware of partitions. Handlers do not receive any event arguments.
MembersUpdated
The MembersUpdated
event triggers whenever the server notifies the client of a new members list. This happens when members are added or removed from the cluster, but also periodically when the server wants to ensure that clients know about members. Handlers receive an instance of the MembersUpdatedEventArgs class, which exposes the following properties:
- AddedMembers: a collection of MemberInfo representing the members that were added to the cluster
- RemovedMembers: a collection of MemberInfo representing the members that were removed from the cluster
- Members: a collection of MemberInfo representing all members in the cluster
ObjectCreated
The ObjectCreated
event triggers whenever the server notifies the client that a new distributed object has been created (for instance, when the server creates a new map named my-map
). Handlers receive an instance of the DistributedObjectCreatedEventArgs class, which exposes the following properties:
- ServiceName: the internal Hazelcast service name (for instance, for maps,
hz:impl:mapService
) - Name: the name of the created object (for instance,
my-map
) - SourceMemberId: the identifier of the member which triggered the event
ObjectDestroyed
The ObjectDestroyed
event triggers whenever the server notifies the client that a distributed object has been destroyed (for instance, when the client requests that the server destroys a map named my-map
). Handlers receive an instance of the DistributedObjectDestroyedEventArgs class, which exposes the following properties:
- ServiceName: the internal Hazelcast service name (for instance, for maps,
hz:impl:mapService
) - Name: the name of the destroyed object (for instance,
my-map
) - SourceMemberId: the identifier of the member which triggered the event
Distributed Objects Events
Each type of distributed object exposes events specific to the type. For instance, IHList<T> exposes the ItemAdded
event:
var list = await client.GetListAsync("my-list");
var id = await list.SubscribeAsync(events => events
.ItemAdded(async (sender, args) =>
{
await DoSomethingWithItem(args.Item);
await DoSomethingElseWithItem(args.Item);
}))
Refer to each distributed object's documentation for details on events.