/// <summary> /// Removes the provided actor and all cataloged state from this registry. /// This method expects an external transaction to be provided for managing atomicity /// </summary> /// <param name="tx">The <see cref="ITransaction"/> this Remove operation is part of.</param> /// <param name="reference"><see cref="ActorReference"/></param> /// <param name="cancellationToken"><see cref="CancellationToken"/></param> /// <returns><see cref="Task"/></returns> protected async Task RemoveActorAsync(ITransaction tx, ActorReference reference, CancellationToken cancellationToken) { var referenceMap = await GetReferenceMapAsync(); var indexableRef = new IndexableActorReference(reference); var index = await referenceMap.TryRemoveAsync(tx, indexableRef, ReliableCollectionDefaults.WriteTimeout, cancellationToken); if (!index.HasValue) { return; } var indexMap = await GetIndexMapAsync(); var state = await indexMap.TryRemoveAsync(tx, index.Value, ReliableCollectionDefaults.WriteTimeout, cancellationToken); if (state.HasValue) { var identityMap = await GetIdentityMapAsync(); await identityMap.TryRemoveAsync(tx, state.Value.Identity, ReliableCollectionDefaults.WriteTimeout, cancellationToken); await OnRemoveActorAsync(tx, state.Value, cancellationToken); } }
/// <summary> /// Catalogs the provided actor and its identity into this registry. /// This method expects an external transaction to be provided for managing atomicity /// </summary> /// <param name="tx">The <see cref="ITransaction"/> this Add operation is part of.</param> /// <param name="reference"><see cref="ActorReference"/> to store into internal state</param> /// <param name="identity">The underlying identity of the provided actor. This is not the actor id</param> /// <param name="cancellationToken"><see cref="CancellationToken"/></param> /// <returns><see cref="Task"/></returns> protected async Task AddActorAsync(ITransaction tx, ActorReference reference, Identity identity, CancellationToken cancellationToken) { var referenceMap = await GetReferenceMapAsync(); var indexMap = await GetIndexMapAsync(); var indexableRef = new IndexableActorReference(reference); var indexLookup = await referenceMap.TryGetValueAsync(tx, indexableRef, ReliableCollectionDefaults.ReadTimeout, cancellationToken); long index; IndexState state; if (indexLookup.HasValue) { index = indexLookup.Value; var stateLookup = await indexMap.TryGetValueAsync(tx, index, ReliableCollectionDefaults.ReadTimeout, cancellationToken); if (!stateLookup.HasValue) { throw new InvalidOperationException($"{indexableRef.StringRepresentation} is missing its internal IndexState"); } state = stateLookup.Value; IndexState newState; if (Equals(state.Identity, identity)) { newState = state; } else { newState = new IndexState { Reference = reference, Identity = identity, Index = index }; // replace old state await indexMap.SetAsync(tx, index, newState, ReliableCollectionDefaults.WriteTimeout, cancellationToken); } await OnUpdateActorAsync(tx, state, newState, cancellationToken); } else { var identityMap = await GetIdentityMapAsync(); var existingIndex = await identityMap.TryGetValueAsync(tx, identity, ReliableCollectionDefaults.ReadTimeout, cancellationToken); if (existingIndex.HasValue) { var existingState = await indexMap.TryGetValueAsync(tx, existingIndex.Value); throw new InvalidOperationException($"{identity} is already registered to Actor {new IndexableActorReference(existingState.Value.Reference).StringRepresentation}"); } var propertiesMap = await GetPropertiesMapAsync(); index = (long)await propertiesMap.AddOrUpdateAsync(tx, "currentIndex", 1L, (key, value) => (long)value + 1, ReliableCollectionDefaults.WriteTimeout, cancellationToken); state = new IndexState { Reference = reference, Identity = identity, Index = index }; await referenceMap.AddAsync(tx, indexableRef, index, ReliableCollectionDefaults.WriteTimeout, cancellationToken); await indexMap.AddAsync(tx, index, state, ReliableCollectionDefaults.WriteTimeout, cancellationToken); await identityMap.AddAsync(tx, identity, index, ReliableCollectionDefaults.WriteTimeout, cancellationToken); await OnAddActorAsync(tx, state, cancellationToken); } }