public bool ShouldReceive(IStreamIdentity stream, object filterData, object item) { if (predicateFunc == null) { predicateFunc = RehydrateStaticFuncion(className, methodName); } return predicateFunc(stream, filterData, item); }
protected FilterPredicateWrapperData(SerializationInfo info, StreamingContext context) { FilterData = info.GetValue(SER_FIELD_DATA, typeof(object)); methodName = info.GetString(SER_FIELD_METHOD); className = info.GetString(SER_FIELD_CLASS); predicateFunc = RehydrateStaticFuncion(className, methodName); }
internal FilterPredicateWrapperData(object filterData, StreamFilterPredicate pred) { CheckFilterPredicateFunc(pred); // Assert expected pre-conditions are always true. FilterData = filterData; predicateFunc = pred; DehydrateStaticFunc(pred); }
private void DehydrateStaticFunc(StreamFilterPredicate pred) { #if DEBUG CheckFilterPredicateFunc(pred); // Assert expected pre-conditions are always true. #endif MethodInfo method = pred.GetMethodInfo(); className = method.DeclaringType.FullName; methodName = method.Name; }
public bool ShouldDeliver(IStreamIdentity stream, object filterData, StreamFilterPredicate shouldReceiveFunc) { foreach (object item in events) { if (shouldReceiveFunc(stream, filterData, item)) return true; // There is something in this batch that the consumer is intereted in, so we should send it. } return false; // Consumer is not interested in any of these events, so don't send. }
/// <summary> /// Subscribe a consumer to this observable using delegates. /// This method is a helper for the IAsyncObservable.SubscribeAsync allowing the subscribing class to inline the /// handler methods instead of requiring an instance of IAsyncObserver. /// </summary> /// <typeparam name="T">The type of object produced by the observable.</typeparam> /// <param name="obs">The Observable object.</param> /// <param name="onNextAsync">Delegte that is called for IAsyncObserver.OnNextAsync.</param> /// <param name="onCompletedAsync">Delegte that is called for IAsyncObserver.OnCompletedAsync.</param> /// <param name="token">The stream sequence to be used as an offset to start the subscription from.</param> /// <param name="filterFunc">Filter to be applied for this subscription</param> /// <param name="filterData">Data object that will be passed in to the filterFunc. /// This will usually contain any paramaters required by the filterFunc to make it's filtering decision.</param> /// <returns>A promise for a StreamSubscriptionHandle that represents the subscription. /// The consumer may unsubscribe by using this handle. /// The subscription remains active for as long as it is not explicitely unsubscribed. /// </returns> /// <exception cref="ArgumentException">Thrown if the supplied stream filter function is not suitable. /// Usually this is because it is not a static method. </exception> public static Task <StreamSubscriptionHandle <object> > SubscribeAsync <T>(this IAsyncObservable <object> obs, Func <T, StreamSequenceToken, Task> onNextAsync, Func <Task> onCompletedAsync, StreamSequenceToken token, StreamFilterPredicate filterFunc = null, object filterData = null) { return(obs.SubscribeAsync(onNextAsync, DefaultOnError, onCompletedAsync, token, filterFunc, filterData)); }
private static StreamFilterPredicate RehydrateStaticFuncion(string funcClassName, string funcMethodName) { Type funcClassType = TypeResolver.ResolveType(funcClassName); MethodInfo method = funcClassType.GetMethod(funcMethodName); StreamFilterPredicate pred = (StreamFilterPredicate)method.CreateDelegate(typeof(StreamFilterPredicate)); #if DEBUG CheckFilterPredicateFunc(pred); // Assert expected pre-conditions are always true. #endif return(pred); }
/// <summary> /// Subscribe a consumer to this observable using delegates. /// This method is a helper for the IAsyncObservable.SubscribeAsync allowing the subscribing class to inline the /// handler methods instead of requiring an instance of IAsyncObserver. /// </summary> /// <typeparam name="T">The type of object produced by the observable.</typeparam> /// <param name="obs">The Observable object.</param> /// <param name="onNextAsync">Delegte that is called for IAsyncObserver.OnNextAsync.</param> /// <param name="onErrorAsync">Delegte that is called for IAsyncObserver.OnErrorAsync.</param> /// <param name="onCompletedAsync">Delegte that is called for IAsyncObserver.OnCompletedAsync.</param> /// <param name="token">The stream sequence to be used as an offset to start the subscription from.</param> /// <param name="filterFunc">Filter to be applied for this subscription</param> /// <param name="filterData">Data object that will be passed in to the filterFunc. /// This will usually contain any paramaters required by the filterFunc to make it's filtering decision.</param> /// <returns>A promise for a StreamSubscriptionHandle that represents the subscription. /// The consumer may unsubscribe by using this handle. /// The subscription remains active for as long as it is not explicitely unsubscribed. /// </returns> /// <exception cref="ArgumentException">Thrown if the supplied stream filter function is not suitable. /// Usually this is because it is not a static method. </exception> public static Task <StreamSubscriptionHandle <object> > SubscribeAsync <T>(this IAsyncObservable <object> obs, Func <T, StreamSequenceToken, Task> onNextAsync, Func <Exception, Task> onErrorAsync, Func <Task> onCompletedAsync, StreamSequenceToken token, StreamFilterPredicate filterFunc = null, object filterData = null) { var genericObserver = new DelegateAsyncObserver <T>(onNextAsync, onErrorAsync, onCompletedAsync); return(obs.SubscribeAsync(genericObserver, token, filterFunc, filterData)); }
private void DehydrateStaticFunc(StreamFilterPredicate pred) { var method = pred.Method; if (!CheckStaticFunc(method)) { throw new ArgumentException("Filter function must be static and not abstract."); } className = method.DeclaringType.FullName; methodName = method.Name; }
public async Task SubscribeWithBadFunc(Guid streamId, string streamNamespace, string providerName) { logger.Info("SubscribeWithBadFunc StreamId={0} StreamProvider={1}Grain={2}", streamId, providerName, this.AsReference <IFilteredStreamConsumerGrain>()); InitStream(streamId, streamNamespace, providerName); var observer = new MyStreamObserver <int>(logger); StreamFilterPredicate filterFunc = BadFunc; // This next call should fail because func is not static await State.Stream.SubscribeAsync(observer, null, filterFunc); }
/// <summary> /// Check that the user-supplied stream predicate function is valid. /// Stream predicate functions must be static and not abstract. /// </summary> private static void CheckFilterPredicateFunc(StreamFilterPredicate predicate) { if (predicate == null) { throw new ArgumentNullException("predicate", "Stream Filter predicate function must not be null."); } MethodInfo method = predicate.GetMethodInfo(); if (!method.IsStatic || method.IsAbstract) { throw new ArgumentException("Stream Filter predicate function must be static and not abstract."); } }
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 bool ShouldDeliver(IStreamIdentity stream, object filterData, StreamFilterPredicate shouldReceiveFunc) { return(_events.Any(item => shouldReceiveFunc(stream, filterData, item))); }
public bool ShouldDeliver(StreamId stream, object filterData, StreamFilterPredicate shouldReceiveFunc) { throw new NotImplementedException(); }
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 (observer is GrainReference) { throw new ArgumentException("On-behalf subscription via grain references is not supported. Only passing of object references is allowed.", "observer"); } 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(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, 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 Task <StreamSubscriptionHandle <T> > SubscribeAsync(IAsyncObserver <T> observer, StreamSequenceToken token, StreamFilterPredicate filterFunc = null, object filterData = null) => throw new NotImplementedException();
/// <summary> /// Check that the user-supplied stream predicate function is valid. /// Stream predicate functions must be static and not abstract. /// </summary> /// <param name="func"></param> private static void CheckFilterPredicateFunc(StreamFilterPredicate predicate) { if (predicate == null) { throw new ArgumentNullException("predicate", "Stream Filter predicate function must not be null."); } MethodInfo method = predicate.GetMethodInfo(); if (!method.IsStatic || method.IsAbstract) { throw new ArgumentException("Stream Filter predicate function must be static and not abstract."); } }
public virtual Task <StreamSubscriptionHandle <object> > SubscribeAsync(IAsyncObserver <object> observer, StreamSequenceToken token, StreamFilterPredicate filterFunc = null, object filterData = null) { return(endpoint.SubscribeAsync(observer, token, filterFunc, filterData)); }
public Task <StreamSubscriptionHandle <T> > SubscribeAsync(IAsyncObserver <T> observer, StreamSequenceToken token, StreamFilterPredicate filterFunc = null, object filterData = null) { return(GetConsumerInterface().SubscribeAsync(observer, token, filterFunc, filterData)); }
internal FilterPredicateWrapperData(object filterData, StreamFilterPredicate pred) { FilterData = filterData; predicateFunc = pred; DehydrateStaticFunc(pred); }
public bool ShouldDeliver(IStreamIdentity stream, object filterData, StreamFilterPredicate shouldReceiveFunc) { // If there is something in this batch that the consumer is interested in, we should send it // else the consumer is not interested in any of these events, so don't send. return(Events.Any(item => shouldReceiveFunc(stream, filterData, item))); }
public bool ShouldDeliver(IStreamIdentity stream, object filterData, StreamFilterPredicate shouldReceiveFunc) { return(true); }
public bool ShouldDeliver(IStreamIdentity stream, object filterData, StreamFilterPredicate shouldReceiveFunc) { // ShouldDeliver is called on a per IBatchContainer basis for each IBatchContainer that composes this BatchContainerBatch. // Therefore, no filtering is done on the BatchContainerBatch level. return(true); }
public Task <StreamSubscriptionHandle <T> > SubscribeAsync( IAsyncObserver <T> observer, StreamSequenceToken token, StreamFilterPredicate filterFunc = null, object filterData = null) => stream.SubscribeAsync(observer, token, filterFunc, filterData);
public bool ShouldDeliver(IStreamIdentity stream, object filterData, StreamFilterPredicate shouldReceiveFunc) { throw new NotSupportedException(); }
public bool ShouldDeliver(IStreamIdentity stream, object filterData, StreamFilterPredicate shouldReceiveFunc) { return(EventData?.Events?.Count > 0); }