/// <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);
        }
        /// <summary>
        ///     Registers an observer. This methods is invoked by an observer.
        /// </summary>
        /// <param name="topic">The topic.</param>
        /// <param name="filterExpressions">Specifies filter expressions.</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 RegisterObserverActorAsync(string topic, IEnumerable <string> filterExpressions, 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));
            }
            IList <string> expressions = filterExpressions as IList <string> ?? filterExpressions.ToList();

            for (int k = 1; k <= ConfigurationHelper.MaxQueryRetryCount; k++)
            {
                try
                {
                    if (entityId.Kind == EntityKind.Actor)
                    {
                        IServerObservableActor actorProxy = ActorProxy.Create <IServerObservableActor>(entityId.ActorId, entityId.ServiceUri);
                        await actorProxy.RegisterObserverAsync(topic, expressions, id);
                    }
                    else
                    {
                        IServerObservableService serviceProxy = entityId.PartitionKey.HasValue
                            ? ServiceProxy.Create <IServerObservableService>(entityId.ServiceUri, new ServicePartitionKey(entityId.PartitionKey.Value))
                            : ServiceProxy.Create <IServerObservableService>(entityId.ServiceUri);
                        await serviceProxy.RegisterObserverAsync(topic, expressions, id);
                    }

                    ConditionalValue <Dictionary <Uri, EntityId> > topicState = await this.StateManager.TryGetStateAsync <Dictionary <Uri, EntityId> >(topic);

                    Dictionary <Uri, EntityId> observableDictionary = topicState.HasValue
                        ? topicState.Value
                        : new Dictionary <Uri, EntityId>();
                    if (observableDictionary.ContainsKey(entityId.EntityUri))
                    {
                        return;
                    }
                    observableDictionary.Add(entityId.EntityUri, entityId);
                    StringBuilder stringBuilder =
                        new StringBuilder(
                            $"Observer successfully registered.\r\n[Observable]: {entityId}\r\n[Observer]: {id}\r\n[Subscription]: Topic=[{topic}]");
                    int i = 1;
                    foreach (string expression in expressions.Where(expression => !string.IsNullOrWhiteSpace(expression)))
                    {
                        stringBuilder.Append($" FilterExpression[{i++}]=[{expression}]");
                    }
                    await this.StateManager.SetStateAsync(topic, observableDictionary);

                    ActorEventSource.Current.Message(stringBuilder.ToString());
                    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);
        }