示例#1
0
        public async Task <StreamSubscriptionHandle <T> > SubscribeAsync(
            IAsyncObserver <T> observer,
            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 (logger.IsVerbose)
            {
                logger.Verbose("Subscribe Observer={0} Token={1}", observer, token);
            }
            await BindExtensionLazy();

            IStreamFilterPredicateWrapper filterWrapper = null;

            if (filterFunc != null)
            {
                filterWrapper = new FilterPredicateWrapperData(filterData, filterFunc);
            }

            if (logger.IsVerbose)
            {
                logger.Verbose("Subscribe - Connecting to Rendezvous {0} My GrainRef={1} Token={2}",
                               pubSub, myGrainReference, token);
            }

            GuidId subscriptionId = pubSub.CreateSubscriptionId(myGrainReference, stream.StreamId);
            await pubSub.RegisterConsumer(subscriptionId, stream.StreamId, streamProviderName, myGrainReference, token, filterWrapper);

            return(myExtension.SetObserver(subscriptionId, stream, observer, filterWrapper));
        }
示例#2
0
        private async Task <StreamSubscriptionHandle <T> > SubscribeAsyncImpl(
            IAsyncObserver <T> observer,
            IAsyncBatchObserver <T> batchObserver,
            StreamSequenceToken token,
            string 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();

            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.InternalStreamId, 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, filterData);

            try
            {
                await pubSub.RegisterConsumer(subscriptionId, stream.InternalStreamId, myGrainReference, filterData);

                return(subriptionHandle);
            }
            catch (Exception)
            {
                // Undo the previous call myExtension.SetObserver.
                myExtension.RemoveObserver(subscriptionId);
                throw;
            }
        }
示例#3
0
        public async Task <StreamSubscriptionHandle <T> > SubscribeAsync(
            IAsyncObserver <T> observer,
            StreamSequenceToken token,
            StreamFilterPredicate filterFunc, object filterData)
        {
            if (token != null && !IsRewindable)
            {
                throw new ArgumentNullException("token", "Passing a non-null token to a non-rewindable IAsyncObservable.");
            }

            if (logger.IsVerbose)
            {
                logger.Verbose("Subscribe Observer={0} Token={1}", observer, token);
            }
            await BindExtensionLazy();

            IStreamFilterPredicateWrapper filterWrapper = null;

            if (filterFunc != null)
            {
                filterWrapper = new FilterPredicateWrapperData(filterData, filterFunc);
            }

            if (!connectedToRendezvous)
            {
                if (logger.IsVerbose)
                {
                    logger.Verbose("Subscribe - Connecting to Rendezvous {0} My GrainRef={1} Token={2}",
                                   pubSub, myGrainReference, token);
                }

                await pubSub.RegisterConsumer(stream.StreamId, streamProviderName, myGrainReference, token, filterWrapper);

                connectedToRendezvous = true;
            }
            else if (filterWrapper != null)
            {
                // Already connected and registered this grain, but also need to register this additional filter too.
                await pubSub.RegisterConsumer(stream.StreamId, streamProviderName, myGrainReference, token, filterWrapper);
            }

            return(myExtension.AddObserver(stream, observer, filterWrapper));
        }
        public async Task <StreamSubscription> AddSubscription(string streamProviderName, StreamId streamId, GrainReference grainRef)
        {
            var consumer         = grainRef.AsReference <IStreamConsumerExtension>();
            var internalStreamId = new InternalStreamId(streamProviderName, streamId);
            var subscriptionId   = streamPubSub.CreateSubscriptionId(internalStreamId, consumer);
            await streamPubSub.RegisterConsumer(subscriptionId, internalStreamId, consumer);

            var newSub = new StreamSubscription(subscriptionId.Guid, streamProviderName, streamId, grainRef.GrainId);

            return(newSub);
        }
示例#5
0
        public async Task <StreamSubscription> AddSubscription(string streamProviderName, IStreamIdentity streamIdentity, GrainReference grainRef)
        {
            var consumer       = grainRef.AsReference <IStreamConsumerExtension>();
            var streamId       = StreamId.GetStreamId(streamIdentity.Guid, streamProviderName, streamIdentity.Namespace);
            var subscriptionId = streamPubSub.CreateSubscriptionId(
                streamId, consumer);
            await streamPubSub.RegisterConsumer(subscriptionId, streamId, streamProviderName, consumer, null);

            var newSub = new StreamSubscription(subscriptionId.Guid, streamProviderName, streamId, grainRef.GrainId);

            return(newSub);
        }
示例#6
0
 public Task RegisterConsumer(GuidId subscriptionId, InternalStreamId streamId, IStreamConsumerExtension streamConsumer)
 {
     return(implicitPubSub.IsImplicitSubscriber(streamConsumer, streamId)
         ? implicitPubSub.RegisterConsumer(subscriptionId, streamId, streamConsumer)
         : explicitPubSub.RegisterConsumer(subscriptionId, streamId, streamConsumer));
 }
示例#7
0
 Task IStreamPubSub.RegisterConsumer(GuidId subscriptionId, StreamId streamId, string streamProvider, IStreamConsumerExtension streamConsumer, IStreamFilterPredicateWrapper filter)
 {
     return(registry.RegisterConsumer(subscriptionId, streamId, streamProvider, streamConsumer, filter));
 }
示例#8
0
 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));
 }
示例#9
0
 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));
 }