public async Task FaultSubscription(GuidId subscriptionId) { PubSubSubscriptionState pubSubState = State.Consumers.FirstOrDefault(s => s.Equals(subscriptionId)); if (pubSubState == null) { return; } try { pubSubState.Fault(); if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug("Setting subscription {0} to a faulted state.", subscriptionId.Guid); } await WriteStateAsync(); await NotifyProducersOfRemovedSubscription(pubSubState.SubscriptionId, pubSubState.Stream); } catch (Exception exc) { logger.Error(ErrorCode.Stream_SetSubscriptionToFaultedFailed, $"Failed to set subscription state to faulted. SubscriptionId {subscriptionId}", exc); // Corrupted state, deactivate grain. DeactivateOnIdle(); throw; } }
public async Task FaultSubscription(GuidId subscriptionId) { PubSubSubscriptionState pubSubState = State.Consumers.FirstOrDefault(s => s.Equals(subscriptionId)); if (pubSubState == null) { return; } pubSubState.Fault(); if (logger.IsVerbose) { logger.Verbose("Setting subscription {0} to a faulted state.", subscriptionId.Guid); } await WriteStateAsync(); await NotifyProducersOfRemovedSubscription(pubSubState.SubscriptionId, pubSubState.Stream); await ClearStateWhenEmpty(); }
public async Task RegisterConsumer( GuidId subscriptionId, StreamId streamId, IStreamConsumerExtension streamConsumer, IStreamFilterPredicateWrapper filter) { counterConsumersAdded.Increment(); PubSubSubscriptionState pubSubState = State.Consumers.FirstOrDefault(s => s.Equals(subscriptionId)); if (pubSubState != null && pubSubState.IsFaulted) { throw new FaultedSubscriptionException(subscriptionId, streamId); } try { if (pubSubState == null) { pubSubState = new PubSubSubscriptionState(subscriptionId, streamId, streamConsumer); State.Consumers.Add(pubSubState); } if (filter != null) { pubSubState.AddFilter(filter); } LogPubSubCounts("RegisterConsumer {0}", streamConsumer); await WriteStateAsync(); counterConsumersTotal.Increment(); } catch (Exception exc) { logger.Error(ErrorCode.Stream_RegisterConsumerFailed, $"Failed to register a stream consumer. Stream: {streamId}, SubscriptionId {subscriptionId}, Consumer: {streamConsumer}", exc); // Corrupted state, deactivate grain. DeactivateOnIdle(); throw; } int numProducers = State.Producers.Count; if (numProducers <= 0) { return; } if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug("Notifying {0} existing producer(s) about new consumer {1}. Producers={2}", numProducers, streamConsumer, Utils.EnumerableToString(State.Producers)); } // Notify producers about a new streamConsumer. var tasks = new List <Task>(); var producers = State.Producers.ToList(); int initialProducerCount = producers.Count; try { foreach (PubSubPublisherState producerState in producers) { tasks.Add(ExecuteProducerTask(producerState, producerState.Producer.AddSubscriber(subscriptionId, streamId, streamConsumer, filter))); } Exception exception = null; try { await Task.WhenAll(tasks); } catch (Exception exc) { exception = exc; } // if the number of producers has been changed, resave state. if (State.Producers.Count != initialProducerCount) { await WriteStateAsync(); counterConsumersTotal.DecrementBy(initialProducerCount - State.Producers.Count); } if (exception != null) { throw exception; } } catch (Exception exc) { logger.Error(ErrorCode.Stream_RegisterConsumerFailed, $"Failed to update producers while register a stream consumer. Stream: {streamId}, SubscriptionId {subscriptionId}, Consumer: {streamConsumer}", exc); // Corrupted state, deactivate grain. DeactivateOnIdle(); throw; } }
public async Task RegisterConsumer( StreamId streamId, IStreamConsumerExtension streamConsumer, StreamSequenceToken token, IStreamFilterPredicateWrapper filter) { // This Where clause will return either zero or one PubSubSubscriptionState var found = State.Consumers.Where(s => s.Equals(streamId, streamConsumer)).ToArray(); PubSubSubscriptionState pubSubState; if (found.Length == 0) { pubSubState = new PubSubSubscriptionState(streamId, streamConsumer, token, filter); State.Consumers.Add(pubSubState); } else { pubSubState = found[0]; if (filter != null) pubSubState.AddFilter(filter); } counterConsumersAdded.Increment(); counterConsumersTotal.Increment(); LogPubSubCounts("RegisterConsumer {0}", streamConsumer); await State.WriteStateAsync(); int numProducers = State.Producers.Count; if (numProducers > 0) { if (logger.IsVerbose) logger.Info("Notifying {0} existing producer(s) about new consumer {1}. Producers={2}", numProducers, streamConsumer, Utils.EnumerableToString(State.Producers)); // Notify producers about a new streamConsumer. var tasks = new List<Task>(); var producers = State.Producers.ToList(); bool someProducersRemoved = false; foreach (var producerState in producers) { PubSubPublisherState producer = producerState; // Capture loop variable if (!IsActiveProducer(producer.Producer)) { // Producer is not active (could be stopping / shutting down) so skip if (logger.IsVerbose) logger.Verbose("Producer {0} on stream {1} is not active - skipping.", producer, streamId); continue; } Task addSubscriberPromise = producer.Producer.AddSubscriber(streamId, streamConsumer, token, filter) .ContinueWith(t => { if (t.IsFaulted) { var exc = t.Exception.GetBaseException(); if (exc is GrainExtensionNotInstalledException) { logger.Warn((int) ErrorCode.Stream_ProducerIsDead, "Producer {0} on stream {1} is no longer active - discarding.", producer, streamId); // This publisher has gone away, so we should cleanup pub-sub state. bool removed = State.Producers.Remove(producer); someProducersRemoved = true; // Re-save state changes at end counterProducersRemoved.Increment(); counterProducersTotal.DecrementBy(removed ? 1 : 0); // And ignore this error } else { throw exc; } } }, TaskContinuationOptions.OnlyOnFaulted); tasks.Add(addSubscriberPromise); } Exception exception = null; try { await Task.WhenAll(tasks); } catch (Exception exc) { exception = exc; } if (someProducersRemoved) await State.WriteStateAsync(); if (exception != null) throw exception; } }
public async Task RegisterConsumer( GuidId subscriptionId, StreamId streamId, IStreamConsumerExtension streamConsumer, IStreamFilterPredicateWrapper filter) { PubSubSubscriptionState pubSubState = State.Consumers.FirstOrDefault(s => s.Equals(subscriptionId)); if (pubSubState == null) { pubSubState = new PubSubSubscriptionState(subscriptionId, streamId, streamConsumer); State.Consumers.Add(pubSubState); } if (pubSubState.IsFaulted) { throw new FaultedSubscriptionException(subscriptionId, streamId); } if (filter != null) { pubSubState.AddFilter(filter); } counterConsumersAdded.Increment(); counterConsumersTotal.Increment(); LogPubSubCounts("RegisterConsumer {0}", streamConsumer); await WriteStateAsync(); int numProducers = State.Producers.Count; if (numProducers <= 0) { return; } if (logger.IsVerbose) { logger.Info("Notifying {0} existing producer(s) about new consumer {1}. Producers={2}", numProducers, streamConsumer, Utils.EnumerableToString(State.Producers)); } // Notify producers about a new streamConsumer. var tasks = new List <Task>(); var producers = State.Producers.ToList(); int initialProducerCount = producers.Count; foreach (var producerState in producers) { PubSubPublisherState producer = producerState; // Capture loop variable if (!IsActiveProducer(producer.Producer)) { // Producer is not active (could be stopping / shutting down) so skip if (logger.IsVerbose) { logger.Verbose("Producer {0} on stream {1} is not active - skipping.", producer, streamId); } continue; } tasks.Add(NotifyProducer(producer, subscriptionId, streamId, streamConsumer, filter)); } Exception exception = null; try { await Task.WhenAll(tasks); } catch (Exception exc) { exception = exc; } // if the number of producers has been changed, resave state. if (State.Producers.Count != initialProducerCount) { await WriteStateAsync(); } if (exception != null) { throw exception; } }