public StreamConsumerData AddConsumer(GuidId subscriptionId, StreamId streamId, IStreamConsumerExtension streamConsumer, IStreamFilterPredicateWrapper filter) { var consumerData = new StreamConsumerData(subscriptionId, streamId, streamConsumer, filter); queueData.Add(subscriptionId, consumerData); lastActivityTime = DateTime.UtcNow; return consumerData; }
public async Task<StreamHandshakeToken> DeliverBatch(GuidId subscriptionId, Immutable<IBatchContainer> batch, StreamHandshakeToken handshakeToken) { foreach (var each in batch.Value.GetEvents<object>()) await handler(each.Item1); return null; }
public StreamConsumerData(GuidId subscriptionId, StreamId streamId, IStreamConsumerExtension streamConsumer, IStreamFilterPredicateWrapper filter) { SubscriptionId = subscriptionId; StreamId = streamId; StreamConsumer = streamConsumer; Filter = filter; }
public bool RemoveConsumer(GuidId subscriptionId, Logger logger) { StreamConsumerData consumer; if (!queueData.TryGetValue(subscriptionId, out consumer)) return false; consumer.SafeDisposeCursor(logger); return queueData.Remove(subscriptionId); }
public Task RegisterConsumer(GuidId subscriptionId, StreamId streamId, string streamProvider, IStreamConsumerExtension streamConsumer, IStreamFilterPredicateWrapper filter) { if (!IsImplicitSubscriber(streamConsumer, streamId)) { throw new ArgumentOutOfRangeException(streamId.ToString(), "Only implicit subscriptions are supported."); } return TaskDone.Done; }
public bool RemoveConsumer(GuidId subscriptionId) { StreamConsumerData consumer; if (!queueData.TryGetValue(subscriptionId, out consumer)) return false; if (consumer.Cursor != null) { // kill cursor activity and ensure it does not start again on this consumer data. consumer.Cursor.Dispose(); consumer.Cursor = null; } return queueData.Remove(subscriptionId); }
public Task OnSubscriptionFailure(GuidId subscriptionId, string streamProviderName, IStreamIdentity streamIdentity, StreamSequenceToken sequenceToken) { return TaskDone.Done; }
Task IStreamPubSub.RegisterConsumer(GuidId subscriptionId, StreamId streamId, string streamProvider, IStreamConsumerExtension streamConsumer, IStreamFilterPredicateWrapper filter) { return registry.RegisterConsumer(subscriptionId, streamId, streamProvider, streamConsumer, filter); }
private async Task <StreamSubscriptionHandle <T> > SubscribeAsyncImpl( IAsyncObserver <T> observer, IAsyncBatchObserver <T> batchObserver, StreamSequenceToken token, StreamFilterPredicate filterFunc = null, object filterData = null) { if (token != null && !IsRewindable) { throw new ArgumentNullException("token", "Passing a non-null token to a non-rewindable IAsyncObservable."); } if (observer is GrainReference) { throw new ArgumentException("On-behalf subscription via grain references is not supported. Only passing of object references is allowed.", nameof(observer)); } if (batchObserver is GrainReference) { throw new ArgumentException("On-behalf subscription via grain references is not supported. Only passing of object references is allowed.", nameof(batchObserver)); } if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug("Subscribe Token={Token}", token); } await BindExtensionLazy(); IStreamFilterPredicateWrapper filterWrapper = null; if (filterFunc != null) { filterWrapper = new FilterPredicateWrapperData(filterData, filterFunc); } if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug("Subscribe - Connecting to Rendezvous {0} My GrainRef={1} Token={2}", pubSub, myGrainReference, token); } GuidId subscriptionId = pubSub.CreateSubscriptionId(stream.StreamId, myGrainReference); // Optimistic Concurrency: // In general, we should first register the subsription with the pubsub (pubSub.RegisterConsumer) // and only if it succeeds store it locally (myExtension.SetObserver). // Basicaly, those 2 operations should be done as one atomic transaction - either both or none and isolated from concurrent reads. // BUT: there is a distributed race here: the first msg may arrive before the call is awaited // (since the pubsub notifies the producer that may immideately produce) // and will thus not find the subriptionHandle in the extension, basically violating "isolation". // Therefore, we employ Optimistic Concurrency Control here to guarantee isolation: // we optimisticaly store subscriptionId in the handle first before calling pubSub.RegisterConsumer // and undo it in the case of failure. // There is no problem with that we call myExtension.SetObserver too early before the handle is registered in pub sub, // since this subscriptionId is unique (random Guid) and no one knows it anyway, unless successfully subscribed in the pubsub. var subriptionHandle = myExtension.SetObserver(subscriptionId, stream, observer, batchObserver, token, filterWrapper); try { await pubSub.RegisterConsumer(subscriptionId, stream.StreamId, streamProviderName, myGrainReference, filterWrapper); return(subriptionHandle); } catch (Exception) { // Undo the previous call myExtension.SetObserver. myExtension.RemoveObserver(subscriptionId); throw; } }
public void RemoveSubscriber_Impl(GuidId subscriptionId, StreamId streamId) { if (IsShutdown) return; StreamConsumerCollection streamData; if (!pubSubCache.TryGetValue(streamId, out streamData)) return; // remove consumer bool removed = streamData.RemoveConsumer(subscriptionId, logger); if (removed && logger.IsVerbose) logger.Verbose((int)ErrorCode.PersistentStreamPullingAgent_10, "Removed Consumer: subscription={0}, for stream {1}.", subscriptionId, streamId); if (streamData.Count == 0) pubSubCache.Remove(streamId); }
public bool TryGetConsumer(GuidId subscriptionId, out StreamConsumerData data) { return queueData.TryGetValue(subscriptionId, out data); }
public async Task<bool> FaultSubscription(StreamId streamId, GuidId subscriptionId) { var streamRendezvous = GetRendezvousGrain(streamId); await streamRendezvous.FaultSubscription(subscriptionId); return true; }
public Task UnregisterConsumer(GuidId subscriptionId, StreamId streamId, string streamProvider) { var streamRendezvous = GetRendezvousGrain(streamId); return(streamRendezvous.UnregisterConsumer(subscriptionId, streamId)); }
public Task RegisterConsumer(GuidId subscriptionId, StreamId streamId, string streamProvider, IStreamConsumerExtension streamConsumer, StreamSequenceToken token, IStreamFilterPredicateWrapper filter) { var streamRendezvous = GetRendezvousGrain(streamId); return(streamRendezvous.RegisterConsumer(subscriptionId, streamId, streamConsumer, token, filter)); }
public Task <bool> FaultSubscription(GuidId subscriptionId, StreamId streamId) { return(IsImplicitSubscriber(subscriptionId, streamId) ? Task.FromResult(false) : explicitPubSub.FaultSubscription(subscriptionId, streamId)); }
private bool IsImplicitSubscriber(GuidId subscriptionId, StreamId streamId) { return(SubscriptionMarker.IsImplicitSubscription(subscriptionId.Guid)); }
public async Task <List <GuidId> > GetAllSubscriptions(StreamId streamId, IStreamConsumerExtension streamConsumer) { return(IsImplicitSubscriber(streamConsumer, streamId) ? new List <GuidId>(new [] { GuidId.GetGuidId(streamConsumer.GetPrimaryKey()) }) : await explicitPubSub.GetAllSubscriptions(streamId, streamConsumer)); }
public Task UnregisterConsumer(GuidId subscriptionId, StreamId streamId, string streamProvider) { return(IsImplicitSubscriber(subscriptionId, streamId) ? TaskDone.Done : explicitPubSub.UnregisterConsumer(subscriptionId, streamId, streamProvider)); }
public Task RegisterConsumer(GuidId subscriptionId, StreamId streamId, string streamProvider, IStreamConsumerExtension streamConsumer, StreamSequenceToken token, IStreamFilterPredicateWrapper filter) { return(IsImplicitSubscriber(streamConsumer, streamId) ? TaskDone.Done : explicitPubSub.RegisterConsumer(subscriptionId, streamId, streamProvider, streamConsumer, token, filter)); }
public Task RegisterConsumer(GuidId subscriptionId, StreamId streamId, string streamProvider, IStreamConsumerExtension streamConsumer, IStreamFilterPredicateWrapper filter) { return implicitPubSub.IsImplicitSubscriber(streamConsumer, streamId) ? implicitPubSub.RegisterConsumer(subscriptionId, streamId, streamProvider, streamConsumer, filter) : explicitPubSub.RegisterConsumer(subscriptionId, streamId, streamProvider, streamConsumer, filter); }
public Task RegisterConsumer(GuidId subscriptionId, StreamId streamId, string streamProvider, IStreamConsumerExtension streamConsumer, IStreamFilterPredicateWrapper filter) { var streamRendezvous = GetRendezvousGrain(streamId); return streamRendezvous.RegisterConsumer(subscriptionId, streamId, streamConsumer, filter); }
public GuidId CreateSubscriptionId(IAddressable requesterAddress, StreamId streamId) { return(GuidId.GetNewGuidId()); }
public StreamSubscriptionHandlerFactory(IStreamProviderManager manager, IStreamIdentity streamId, string providerName, GuidId subscriptionId) { this.manager = manager; this.StreamId = streamId; this.ProviderName = providerName; this.SubscriptionId = subscriptionId; }
public async Task RemoveSubscription(string streamProviderName, IStreamIdentity streamId, Guid subscriptionId) { await streamPubSub.UnregisterConsumer(GuidId.GetGuidId(subscriptionId), StreamId.GetStreamId(streamId.Guid, streamProviderName, streamId.Namespace), streamProviderName); }
// Called by rendezvous when new remote subscriber subscribes to this stream. private async Task AddSubscriber_Impl( GuidId subscriptionId, StreamId streamId, IStreamConsumerExtension streamConsumer, StreamSequenceToken cacheToken, IStreamFilterPredicateWrapper filter) { if (IsShutdown) return; StreamConsumerCollection streamDataCollection; if (!pubSubCache.TryGetValue(streamId, out streamDataCollection)) { streamDataCollection = new StreamConsumerCollection(DateTime.UtcNow); pubSubCache.Add(streamId, streamDataCollection); } StreamConsumerData data; if (!streamDataCollection.TryGetConsumer(subscriptionId, out data)) data = streamDataCollection.AddConsumer(subscriptionId, streamId, streamConsumer, filter ?? DefaultStreamFilter); if (await DoHandshakeWithConsumer(data, cacheToken)) { if (data.State == StreamConsumerDataState.Inactive) RunConsumerCursor(data, data.Filter).Ignore(); // Start delivering events if not actively doing so } }
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) { 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(subscriptionId, streamId, streamConsumer, 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.ExecuteSynchronously); tasks.Add(addSubscriberPromise); } Exception exception = null; try { await Task.WhenAll(tasks); } catch (Exception exc) { exception = exc; } if (someProducersRemoved) { await WriteStateAsync(); } if (exception != null) { throw exception; } } }
internal bool IsImplicitSubscriber(GuidId subscriptionId, StreamId streamId) { return SubscriptionMarker.IsImplicitSubscription(subscriptionId.Guid); }
public Task AddSubscriber(GuidId subscriptionId, InternalStreamId streamId, IStreamConsumerExtension streamConsumer, string filterData) { return(Task.CompletedTask); }
internal void RemoveRemoteSubscriber(GuidId subscriptionId) { Tuple<IStreamConsumerExtension, IStreamFilterPredicateWrapper> ignore; consumers.TryRemove(subscriptionId, out ignore); if (consumers.Count == 0) { // Unsubscribe from PubSub? } }
public Task RemoveSubscriber(GuidId subscriptionId, InternalStreamId streamId) { return(Task.CompletedTask); }
internal void AddRemoteSubscriber(GuidId subscriptionId, IStreamConsumerExtension streamConsumer, string filterData) { consumers.TryAdd(subscriptionId, (streamConsumer, filterData)); }
public Task <bool> FaultSubscription(StreamId streamId, GuidId subscriptionId) { return(Task.FromResult(false)); }
internal void AddRemoteSubscriber(GuidId subscriptionId, IStreamConsumerExtension streamConsumer, IStreamFilterPredicateWrapper filter) { consumers.TryAdd(subscriptionId, Tuple.Create(streamConsumer, filter)); }
public StreamSubscriptionHandleImpl(GuidId subscriptionId, StreamImpl <T> streamImpl) : this(subscriptionId, null, null, streamImpl, null, null) { }
Task<bool> IStreamPubSub.FaultSubscription(StreamId streamId, GuidId subscriptionId) { return registry.FaultSubscription(streamId, subscriptionId); }
public Task RemoveSubscriber(GuidId subscriptionId, StreamId streamId) { RemoveSubscriber_Impl(subscriptionId, streamId); return(TaskDone.Done); }
Task IStreamPubSub.UnregisterConsumer(GuidId subscriptionId, StreamId streamId, string streamProvider) { return registry.UnregisterConsumer(subscriptionId, streamId, streamProvider); }
public async Task <StreamSequenceToken> DeliverItem(GuidId subscriptionId, Immutable <object> item, StreamSequenceToken currentToken, StreamSequenceToken prevToken) { await handler(item); return(null); }
public Task<bool> FaultSubscription(StreamId streamId, GuidId subscriptionId) { return implicitPubSub.IsImplicitSubscriber(subscriptionId, streamId) ? implicitPubSub.FaultSubscription(streamId, subscriptionId) : explicitPubSub.FaultSubscription(streamId, subscriptionId); }
public Task <StreamSequenceToken> GetSequenceToken(GuidId subscriptionId) => Task.FromResult((StreamSequenceToken)null);
public Task UnregisterConsumer(GuidId subscriptionId, StreamId streamId, string streamProvider) { return implicitPubSub.IsImplicitSubscriber(subscriptionId, streamId) ? implicitPubSub.UnregisterConsumer(subscriptionId, streamId, streamProvider) : explicitPubSub.UnregisterConsumer(subscriptionId, streamId, streamProvider); }
public Task CompleteStream(GuidId subscriptionId) => TaskDone.Done;
public Task UnregisterConsumer(GuidId subscriptionId, StreamId streamId, string streamProvider) { var streamRendezvous = GetRendezvousGrain(streamId); return streamRendezvous.UnregisterConsumer(subscriptionId, streamId); }
public Task ErrorInStream(GuidId subscriptionId, Exception exc) => TaskDone.Done;
public StreamConsumerData AddConsumer(GuidId subscriptionId, StreamId streamId, IStreamConsumerExtension streamConsumer, StreamSequenceToken token, IStreamFilterPredicateWrapper filter) { var consumerData = new StreamConsumerData(subscriptionId, streamId, streamConsumer, filter); queueData.Add(subscriptionId, consumerData); return consumerData; }
public Task RemoveSubscriber(GuidId subscriptionId, StreamId streamId) { RemoveSubscriber_Impl(subscriptionId, streamId); return(Task.CompletedTask); }
public bool Contains(GuidId subscriptionId) { return queueData.ContainsKey(subscriptionId); }
public bool Contains(GuidId subscriptionId) { return(queueData.ContainsKey(subscriptionId)); }
public Task AddSubscriber( GuidId subscriptionId, StreamId streamId, IStreamConsumerExtension streamConsumer, IStreamFilterPredicateWrapper filter) { if (logger.IsVerbose) logger.Verbose((int)ErrorCode.PersistentStreamPullingAgent_09, "AddSubscriber: Stream={0} Subscriber={1}.", streamId, streamConsumer); // cannot await here because explicit consumers trigger this call, so it could cause a deadlock. AddSubscriber_Impl(subscriptionId, streamId, streamConsumer, null, filter) .LogException(logger, ErrorCode.PersistentStreamPullingAgent_26, String.Format("Failed to add subscription for stream {0}." , streamId)) .Ignore(); return TaskDone.Done; }
public bool TryGetConsumer(GuidId subscriptionId, out StreamConsumerData data) { return(queueData.TryGetValue(subscriptionId, out data)); }
public Task RemoveSubscriber(GuidId subscriptionId, StreamId streamId) { RemoveSubscriber_Impl(subscriptionId, streamId); return TaskDone.Done; }
public Task OnSubscriptionFailure(GuidId subscriptionId, string streamProviderName, IStreamIdentity streamIdentity, StreamSequenceToken sequenceToken) { return(TaskDone.Done); }
internal FaultedSubscriptionException(GuidId subscriptionId, StreamId streamId) : base(string.Format(ErrorStringFormat, subscriptionId.Guid, streamId)) { }
public Task<bool> FaultSubscription(StreamId streamId, GuidId subscriptionId) { return Task.FromResult(false); }
private async Task DeliverToRemote(IStreamConsumerExtension remoteConsumer, StreamId streamId, GuidId subscriptionId, object item, bool optimizeForImmutableData, bool fireAndForgetDelivery) { try { if (optimizeForImmutableData) { await remoteConsumer.DeliverImmutable(subscriptionId, streamId, new Immutable <object>(item), null, null); } else { await remoteConsumer.DeliverMutable(subscriptionId, streamId, item, null, null); } } catch (ClientNotAvailableException) { Tuple <IStreamConsumerExtension, IStreamFilterPredicateWrapper> discard; if (consumers.TryRemove(subscriptionId, out discard)) { streamPubSub.UnregisterConsumer(subscriptionId, streamId, streamId.ProviderName).Ignore(); logger.Warn(ErrorCode.Stream_ConsumerIsDead, "Consumer {0} on stream {1} is no longer active - permanently removing Consumer.", remoteConsumer, streamId); } } catch (Exception ex) { if (!fireAndForgetDelivery) { throw; } this.logger.LogWarning(ex, "Failed to deliver message to consumer on {SubscriptionId} for stream {StreamId}.", subscriptionId, streamId); } }
public Task UnregisterConsumer(GuidId subscriptionId, StreamId streamId, string streamProvider) { return TaskDone.Done; }
private async Task NotifyComplete(IStreamConsumerExtension remoteConsumer, GuidId subscriptionId, StreamId streamId, bool fireAndForgetDelivery) { try { await remoteConsumer.CompleteStream(subscriptionId); } catch (Exception ex) { if (!fireAndForgetDelivery) { throw; } this.logger.LogWarning(ex, "Failed to notify consumer of stream completion on {SubscriptionId} for stream {StreamId}.", subscriptionId, streamId); } }
internal LocalObjectData(IAddressable obj, GuidId observerId, IGrainMethodInvoker invoker) { LocalObject = new WeakReference(obj); ObserverId = observerId; Invoker = invoker; Messages = new Queue<Message>(); Running = false; }
internal void AddRemoteSubscriber(GuidId subscriptionId, IStreamConsumerExtension streamConsumer) { consumers.TryAdd(subscriptionId, streamConsumer); }