/// <summary> /// Unregisters an observer. This methods is invoked by an observer. /// </summary> /// <param name="topic">The topic.</param> /// <param name="entityId">The entity id of the observable.</param> /// This method is called by a management service or actor. /// <returns>The asynchronous result of the operation.</returns> public async Task UnregisterObserverActorAsync(string topic, EntityId entityId) { EntityId id = await this.GetEntityIdAsync(); if (id == null) { return; } if (string.IsNullOrWhiteSpace(topic)) { throw new ArgumentException($"The {nameof(topic)} parameter cannot be null.", nameof(topic)); } if (entityId == null) { throw new ArgumentException($"The {nameof(entityId)} parameter cannot be null.", nameof(entityId)); } for (int k = 1; k <= ConfigurationHelper.MaxQueryRetryCount; k++) { try { ConditionalValue <Dictionary <Uri, EntityId> > topicState = await this.StateManager.TryGetStateAsync <Dictionary <Uri, EntityId> >(topic); if (!topicState.HasValue) { ActorEventSource.Current.Message( $"Observer not registered to the specified topic.\r\n[Observable]: {entityId}\r\n[Observer]: {id}\r\n[Publication]: Topic=[{topic}]"); return; } Dictionary <Uri, EntityId> observableDictionary = topicState.Value; if (!observableDictionary.ContainsKey(entityId.EntityUri)) { ActorEventSource.Current.Message( $"Observer not registered to the specified observable.\r\n[Observable]: {entityId}\r\n[Observer]: {id}\r\n[Publication]: Topic=[{topic}]"); return; } if (entityId.Kind == EntityKind.Actor) { IServerObservableActor actorProxy = ActorProxy.Create <IServerObservableActor>(entityId.ActorId, entityId.ServiceUri); await actorProxy.UnregisterObserverAsync(topic, id); } else { IServerObservableService serviceProxy = entityId.PartitionKey.HasValue ? ServiceProxy.Create <IServerObservableService>(entityId.ServiceUri, new ServicePartitionKey(entityId.PartitionKey.Value)) : ServiceProxy.Create <IServerObservableService>(entityId.ServiceUri); await serviceProxy.UnregisterObserverAsync(topic, id); } observableDictionary.Remove(entityId.EntityUri); if (!observableDictionary.Any()) { await this.StateManager.TryRemoveStateAsync(topic); } else { await this.StateManager.SetStateAsync(topic, observableDictionary); } ActorEventSource.Current.Message( $"Observer successfully unregistered.\r\n[Observable]: {entityId}\r\n[Observer]: {id}\r\n[Subscription]: Topic=[{topic}]"); return; } catch (FabricTransientException ex) { ActorEventSource.Current.Error(ex); } catch (AggregateException ex) { foreach (Exception e in ex.InnerExceptions) { ActorEventSource.Current.Error(e); } throw; } catch (Exception ex) { ActorEventSource.Current.Error(ex); throw; } await Task.Delay(ConfigurationHelper.BackoffQueryDelay); } throw new TimeoutException(Constants.RetryTimeoutExhausted); }