Example #1
0
        public void CreateSubscription(SubscriptionInfo subscriptionInfo, bool isUserOperation = true)
        {
            SubscriptionIdentifier    subscriptionIdentifier   = new SubscriptionIdentifier(subscriptionInfo.SubscriptionId, subscriptionInfo.SubPolicyType);
            ClientSubscriptionManager clientSubscriptionManger = null;


            if (AddSubscription(subscriptionInfo, subscriptionIdentifier, isUserOperation))
            {
                lock (_mutex)
                {
                    if (subscriptionInfo.SubPolicyType != SubscriptionPolicyType.EventSubscription)
                    {
                        _subscriptionLoadBalancer.Add(subscriptionIdentifier);
                    }

                    //while state transfer if any durable subscription has no active subscriber
                    if (subscriptionInfo.ClientId != null)
                    {
                        if (!_subscribers.TryGetValue(subscriptionInfo.ClientId, out clientSubscriptionManger))
                        {
                            clientSubscriptionManger = new ClientSubscriptionManager(this, subscriptionInfo.ClientId);
                            _subscribers.Add(subscriptionInfo.ClientId, clientSubscriptionManger);
                        }

                        clientSubscriptionManger.AddSubscription(subscriptionInfo);
                    }
                }

                if (_listener != null)
                {
                    _listener.OnSubscriptionCreated(this);
                }
            }
        }
        public async void Test_filter_matches_one_of_two()
        {
            // Arrange
            _mockFilterFactory.Setup(f => f.GetExpressionAsync("Topic = 'topic0' and A"))
            .Returns(() => Task.FromResult(Mock.Of <IFilterExpression>(e => e.EvaluateAsync(It.IsAny <IReadOnlyDictionary <string, object> >()) == Task.FromResult <IComparable>(true))));
            _mockFilterFactory.Setup(f => f.GetExpressionAsync("Topic = 'topic0' and B"))
            .Returns(() => Task.FromResult(Mock.Of <IFilterExpression>(e => e.EvaluateAsync(It.IsAny <IReadOnlyDictionary <string, object> >()) == Task.FromResult <IComparable>(false))));

            var subscriptionFoo    = new SubscriptionIdentifier("topic0", "A");
            var subscriptionOffice = new SubscriptionIdentifier("topic0", "B");

            var subscriptions = new[]
            {
                new KeyValuePair <SubscriptionIdentifier, MessageBusCallbackDelegate>(subscriptionOffice,
                                                                                      (topic, filter, message) => Assert.Fail("You are not supposed to be here.")),
                new KeyValuePair <SubscriptionIdentifier, MessageBusCallbackDelegate>(subscriptionFoo,
                                                                                      (topic, filter, message) => Assert.Fail("You are not supposed to be here."))
            };

            // Act
            var callbacks = await _filteringService.Filter(_messageContextMock.Object, subscriptions);

            //Assert
            Assert.That(callbacks.Count() == 1, Is.True);
            Assert.That(callbacks.Any(p => p.Key == subscriptionFoo), Is.True);
            Assert.That(callbacks.Any(p => p.Key == subscriptionOffice), Is.False);
        }
Example #3
0
        private bool AssignMessageToSubscriber(SubscriptionInfo subscriptionInfo, Message message)
        {
            HashSet <SubscriptionIdentifier> subscriptionIdentifierList;
            ClientSubscriptionManager        client;
            SubscriptionIdentifier           subscriptionIdentity = new SubscriptionIdentifier(subscriptionInfo.SubscriptionId, subscriptionInfo.SubPolicyType);
            Subscriptions subscriptions;

            _subscriptions.TryGetValue(subscriptionIdentity, out subscriptions);

            if (subscriptions == null)
            {
                return(false);
            }

            if (/*client.IsActive &&*/ subscriptions.IsActive())
            {
                lock (_mutex)
                {
                    if (_subscribers.TryGetValue(subscriptionInfo.ClientId, out client))
                    {
                        if (client.AssignMessageToSubscription(message, subscriptionInfo))
                        {
                            SubscriptionIdentifier subIdentifier = new SubscriptionIdentifier(subscriptionInfo.SubscriptionId, subscriptionInfo.SubPolicyType);

                            HashSet <SubscriptionIdentifier> subscriptionId;
                        }
                        return(true);
                    }
                }
            }

            return(false);
        }
        public async void Test_logging_when_filter_fail()
        {
            var subscriptionFoo    = new SubscriptionIdentifier("topic0", "A");
            var subscriptionOffice = new SubscriptionIdentifier("topic0", "B");

            _mockFilterFactory.Setup(f => f.GetExpressionAsync("Topic = 'topic0' and A"))
            .Returns(() => Task.FromResult(Mock.Of <IFilterExpression>(e => e.EvaluateAsync(It.IsAny <IReadOnlyDictionary <string, object> >()) == Task.FromResult <IComparable>(true))));
            var subscriptions = new[]
            {
                new KeyValuePair <SubscriptionIdentifier, MessageBusCallbackDelegate>(subscriptionOffice,
                                                                                      (topic, filter, message) => Assert.Fail("You are not supposed to be here.")),
                new KeyValuePair <SubscriptionIdentifier, MessageBusCallbackDelegate>(subscriptionFoo,
                                                                                      (topic, filter, message) => Assert.Fail("You are not supposed to be here."))
            };

            // Act
            var callbacks = await _filteringService.Filter(_messageContextMock.Object, subscriptions);

            // Assert

            // test that we traced a message
            _mockTraceListener.Verify((t) => t.TraceEvent(
                                          It.IsAny <TraceEventCache>(),
                                          It.IsAny <string>(),
                                          TraceEventType.Error,
                                          It.IsAny <int>(),
                                          It.IsAny <string>(),
                                          It.IsAny <object[]>()));

            // trace that even though we had an error, the callbacks which were tested successfully came back
            Assert.That(callbacks.Any(p => p.Key == subscriptionFoo), Is.True);
        }
Example #5
0
        internal void UnSubscribe(TopicSubscription subscription, bool remove = false, bool dispose = false)
        {
            try
            {
                SubscriptionIdentifier subscriptionIdentifier = new SubscriptionIdentifier(subscription.SubscriptionName, subscription.GetSubscriptionPolicyType);
                _readerWriterLock.AcquireReaderLock(Timeout.Infinite);
                if (_isDisposed)
                {
                    return;
                }

                _cacheImpl.UnSubscribe(Name, subscription.SubscriptionName, subscription.GetSubscriptionPolicyType, SubscriptionType.Subscriber, dispose);

                if (remove)
                {
                    lock (_subscriptions)
                    {
                        _subscriptions.Remove(subscriptionIdentifier);
                    }
                }

                _parent.StopPollingIfRequired(this);
            }
            finally
            {
                _readerWriterLock.ReleaseReaderLock();
            }
        }
Example #6
0
        private bool RequeMessage(Message message, SubscriptionIdentifier subscriptionIdentifier)
        {
            HashSet <SubscriptionIdentifier> assignedSubscriptions;


            if (!message.MessageMetaData.EverAcknowledged && message.MessageMetaData.IsAssigned && !message.MessageMetaData.HasSubscriptions)
            {
                message.MessageMetaData.IsAssigned    = false;
                message.MessageMetaData.AssigmentTime = null;

                //agains; enque for assignment
                switch (message.MessageMetaData.SubscriptionType)
                {
                case SubscriptionType.Subscriber:
                    _unassignedMessages.Enqueue(message.MessageId, message);
                    break;
                }
                return(true);
            }
            else if (message.MessageMetaData.Delivered)
            {
                _deliveredMessages.Enqueue(message.MessageId, message);
                if (_listener != null)
                {
                    _listener.OnMessageDelivered(this);
                }
            }

            return(false);
        }
        public async void Test_dispatch_dispatches()
        {
            // Arrange
            var subscription = new SubscriptionIdentifier("foo", "B=1");
            MessageBusCallbackDelegate emptyDelegate        = (topic, filter, message) => { };
            MessageBusCallbackDelegate testCallbackDelegate = (topic, filter, message) =>
            {
                Assert.Pass("Callback successfully called");
            };
            var mockMessage = new Mock <IMagicHubMessage>();

            _mockFilteringService
            .Setup(f =>
                   f.Filter(
                       It.IsAny <IReadOnlyDictionary <string, object> >(),
                       It.IsAny <IEnumerable <KeyValuePair <SubscriptionIdentifier, MessageBusCallbackDelegate> > >()))
            .Returns(Task.FromResult <IEnumerable <KeyValuePair <SubscriptionIdentifier, MessageBusCallbackDelegate> > >(new[]
            {
                new KeyValuePair <SubscriptionIdentifier, MessageBusCallbackDelegate>(
                    subscription,
                    testCallbackDelegate)
            }));

            _dispatcher.Subscribe(subscription, emptyDelegate);

            // Act
            await _dispatcher.DispatchMessage(mockMessage.Object);
        }
        internal void ClientDisconnected(SubscriptionInfo subscriptionInfo)
        {
            lock (this)
            {
                SubscriptionIdentifier   subscriptionIdentifier   = new SubscriptionIdentifier(subscriptionInfo.SubscriptionId, subscriptionInfo.SubPolicyType);
                SubscriptionIdentifier[] messageSubscriptionKey   = new SubscriptionIdentifier[_messageSubscriptions.Count];
                SubscriptionIdentifier[] deliverySubscriptionKeys = new SubscriptionIdentifier[_deliverySubscriptions.Count];
                _deliverySubscriptions.Keys.CopyTo(deliverySubscriptionKeys, 0);

                _messageSubscriptions.Keys.CopyTo(messageSubscriptionKey, 0);
                foreach (var item in messageSubscriptionKey)
                {
                    subscriptionInfo.SubscriptionId = item.SubscriptionName;
                    subscriptionInfo.Type           = Common.Enum.SubscriptionType.Subscriber;
                    subscriptionInfo.SubPolicyType  = item.SubscriptionPolicy;
                    RemoveSubscription(subscriptionInfo);
                }

                foreach (var item in deliverySubscriptionKeys)
                {
                    subscriptionInfo.SubscriptionId = item.SubscriptionName;
                    subscriptionInfo.SubPolicyType  = item.SubscriptionPolicy;
                    subscriptionInfo.Type           = Common.Enum.SubscriptionType.Publisher;
                    RemoveSubscription(subscriptionInfo);
                }

                if (_subscriptionListener != null)
                {
                    _subscriptionListener.OnSubscriptionInstanceRemoved(messageSubscriptionKey, this.ClientID);
                }
            }
        }
Example #9
0
        private bool RemoveSubscription(SubscriptionIdentifier subIdentifier, SubscriptionInfo subInfo, bool isDispose = false)
        {
            Subscriptions subscription;

            lock (_mutex)
            {
                if (_subscriptions.TryGetValue(subIdentifier, out subscription))
                {
                    if (subIdentifier.SubscriptionPolicy == SubscriptionPolicyType.NonDurableExclusiveSubscription)
                    {
                        _subscriptions.Remove(subIdentifier);
                    }
                    else
                    {
                        subscription.Remove(subInfo.ClientId);

                        if (!subscription.IsActive() && isDispose == false)
                        {
                            _subscriptions.Remove(subIdentifier);
                            //_subscriptionExpirationIndex.Remove(subIdentifier);
                        }
                    }
                }
            }

            return(RemoveSubscriber(subInfo));
        }
        public bool AssignMessageToSubscription(Message message, SubscriptionInfo subscriptionInfo)
        {
            lock (this)
            {
                SubscriptionIdentifier subscriptionIdentifier = new SubscriptionIdentifier(subscriptionInfo.SubscriptionId, subscriptionInfo.SubPolicyType);

                if (_dipsoed)
                {
                    return(false);
                }
                if (message.MessageMetaData.SubscriptionType != subscriptionInfo.Type)
                {
                    return(false);
                }

                Subscribers subscription = null;
                switch (message.MessageMetaData.SubscriptionType)
                {
                case Common.Enum.SubscriptionType.Subscriber:
                    if (subscriptionInfo.SubscriptionId != null)
                    {
                        if (!_messageSubscriptions.TryGetValue(subscriptionIdentifier, out subscription))
                        {
                            return(false);
                        }
                    }

                    if (_messageSubscriptions.Count > 0 && !_messages.Contains(message.MessageId))
                    {
                        _messages.Add(message.MessageId, message);
                    }
                    break;

                case Common.Enum.SubscriptionType.Publisher:
                    if (!_deliverySubscriptions.TryGetValue(subscriptionIdentifier, out subscription))
                    {
                        return(false);
                    }

                    if (!_delivryNotificationMessages.Contains(message.MessageId))
                    {
                        _delivryNotificationMessages.Add(message.MessageId, message);
                    }
                    break;
                }
                message.MessageMetaData.RegisterSubscription(this);
                //in case of single subscriber assignment; we add subscriber id to the message
                bool any = message.MessageMetaData.DeliveryOption == Runtime.Caching.DeliveryOption.Any ||
                           message.MessageMetaData.SubscriptionType == Common.Enum.SubscriptionType.Publisher;

                if (any && subscription != null)
                {
                    message.MessageMetaData.AddRecepient(subscription.ID);
                    message.MessageMetaData.AddToRecepientList(subscriptionIdentifier);
                }
            }
            return(true);
        }
Example #11
0
        public void OnSubscritionRefresh(SubscriptionIdentifier subscriptionId)
        {
            Subscriptions subscriptions;

            if (_subscriptions.TryGetValue(subscriptionId, out subscriptions))
            {
                subscriptions.ResetExpiration();
            }
        }
Example #12
0
        public bool AddSubscription(SubscriptionInfo subscriptionInfo, SubscriptionIdentifier subscriptionIdentifier, bool isUserOperation = true)
        {
            Subscriptions subscription;
            bool          created = true;

            lock (_mutex)
            {
                if (_subscriptions.TryGetValue(subscriptionIdentifier, out subscription))
                {
                    if (subscription.SubscriptionPolicyType == SubscriptionPolicyType.NonDurableExclusiveSubscription && isUserOperation)
                    {
                        created = false;
                    }
                    else
                    {
                        if (subscriptionInfo.SubPolicyType != SubscriptionPolicyType.NonDurableExclusiveSubscription)
                        {
                            created = subscription.AddSubscriber(subscriptionInfo.ClientId);
                        }
                    }
                }
                else
                {
                    switch (subscriptionInfo.SubPolicyType)
                    {
                    case SubscriptionPolicyType.NonDurableExclusiveSubscription:
                        FeatureUsageCollector.Instance.GetFeature(FeatureEnum.data_sharing).UpdateUsageTime();
                        FeatureUsageCollector.Instance.GetFeature(FeatureEnum.pubsub, FeatureEnum.data_sharing).UpdateUsageTime();
                        FeatureUsageCollector.Instance.GetFeature(FeatureEnum.non_durable_subscription, FeatureEnum.pubsub).UpdateUsageTime();

                        if (subscriptionInfo.Type != SubscriptionType.Publisher)
                        {
                            subscription = new ExclusiveSubscriptions(subscriptionInfo.ClientId, subscriptionInfo.SubscriptionId, subscriptionInfo.SubPolicyType, subscriptionInfo.Expiration, _context);
                        }
                        else
                        {
                            subscription = new ExclusiveSubscriptions(subscriptionInfo.ClientId, subscriptionInfo.SubscriptionId, subscriptionInfo.SubPolicyType, subscriptionInfo.Expiration, _context, subscriptionInfo.Type);

                            FeatureUsageCollector.Instance.GetFeature(FeatureEnum.data_sharing).UpdateUsageTime();
                            FeatureUsageCollector.Instance.GetFeature(FeatureEnum.pubsub, FeatureEnum.data_sharing).UpdateUsageTime();
                            FeatureUsageCollector.Instance.GetFeature(FeatureEnum.delivery_failure_notificatiion, FeatureEnum.pubsub).UpdateUsageTime();
                        }

                        break;

                    case SubscriptionPolicyType.EventSubscription:
                        subscription = new EventSubscriptions(subscriptionInfo.ClientId, subscriptionInfo.SubscriptionId, subscriptionInfo.SubPolicyType, subscriptionInfo.Expiration, _context, subscriptionInfo.Type);
                        break;
                    }
                    _subscriptions.Add(subscriptionIdentifier, subscription);
                }
                return(created);
            }
        }
Example #13
0
        /// <summary>
        ///     Unsubscribe topic
        /// </summary>
        /// <param name="connectionId">The SignalR connectionID associated with this subscription.</param>
        /// <param name="topic">The topic, without filter, with nnt: qualifier, if applicable.</param>
        /// <param name="filter">The filter, in SQL-92 format.</param>
        /// <returns></returns>
        public async Task Unsubscribe(string connectionId, string topic, string filter)
        {
            await _subscriptionMutex.WaitAsync();

            Trace.TraceVerbose("Unsubscribe. Entered monitor. ConnectionId={0} Topic={1} Filter={2}", connectionId, topic, filter);
            try
            {
                List <string> subscribedSelectors;

                if (_subscribedSelectorsForConnection.TryGetValue(connectionId, out subscribedSelectors))
                {
                    var subscription = new SubscriptionIdentifier(topic, filter);


                    await MessageBus.Unsubscribe(topic, filter);

                    _counters.NumberOfSubscriptionsTotal.Decrement();
                    Trace.TraceVerbose("Unsubscribe. MessageBus unsubscribed. ConnectionId={0} Topic={1} Filter={2}", connectionId, topic, filter);
                    subscribedSelectors.Remove(subscription.Selector);

                    if (subscribedSelectors.Count == 0)
                    {
                        _subscribedSelectorsForConnection.TryRemove(connectionId, out subscribedSelectors);
                    }


                    await Groups.Remove(connectionId, subscription.Selector);

                    Trace.TraceVerbose("Unsubscribe. Group removed. ConnectionId={0} Topic={1} Filter={2}", connectionId, topic, filter);

                    // if it's the last topic, clean up resource
                }
            }
            catch (AggregateException agx)
            {
                agx.Handle((e) =>
                {
                    Trace.TraceError(e);
                    return(false);
                });
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex);
                throw;
            }
            finally
            {
                Trace.TraceVerbose("Unsubscribe. Releasing monitor. ConnectionId={0} Topic={1} Filter={2}", connectionId, topic, filter);
                _subscriptionMutex.Release();
                Trace.TraceVerbose("Unsubscribe. Released monitor. ConnectionId={0} Topic={1} Filter={2}", connectionId, topic, filter);
            }
        }
Example #14
0
        public void Test_tostring()
        {
            // Arrange
            var identifier = new SubscriptionIdentifier("foo", @"{
                                                                    ""LHS"": ""Foo"",
                                                                    ""OP"": ""EQ"",
                                                                    ""RHS"": 5        
                                                                  }");

            // Assert
            Assert.That(identifier.ToString() == identifier.Selector);
        }
Example #15
0
        public void Test_constructor_equals_false_on_wrong_type()
        {
            // Arrange
            var identifier = new SubscriptionIdentifier("foo", @"{
                                                                    ""LHS"": ""Foo"",
                                                                    ""OP"": ""EQ"",
                                                                    ""RHS"": 5        
                                                                  }");


            // Assert
            Assert.That(identifier, Is.Not.EqualTo("kittens"));
        }
Example #16
0
        public void Test_that_equals_returns_false_for_kittens()
        {
            // Arrange
            var identifier = new SubscriptionIdentifier("foo", @"{
                                                                    ""LHS"": ""Foo"",
                                                                    ""OP"": ""EQ"",
                                                                    ""RHS"": 5        
                                                                  }");
            var kitten     = "meow";

            // Assert
            Assert.That(identifier, Is.Not.EqualTo(kitten));
            // We have shown that a subscription identifier is not a kitten!
        }
Example #17
0
        internal ITopicSubscription RegisterSubscriptions(string subscriptionName, MessageReceivedCallback onMessageReceivedCallback, SubscriptionPolicyType subscriptionPolicy = SubscriptionPolicyType.NonDurableExclusiveSubscription, TimeSpan?timeSpan = default(TimeSpan?))
        {
            try
            {
                _readerWriterLock.AcquireReaderLock(Timeout.Infinite);
                SubscriptionIdentifier subscriptionIdentifier = new SubscriptionIdentifier(subscriptionName, subscriptionPolicy);
                TopicSubscription      topicSubscription      = GetExistingSubscription(subscriptionIdentifier, subscriptionPolicy);

                if (topicSubscription == null)
                {
                    topicSubscription = new TopicSubscription(this, subscriptionName, subscriptionPolicy, onMessageReceivedCallback);
                    DateTime creationTime = DateTime.Now;
                    topicSubscription.CreationTime = creationTime.Ticks;
                    topicSubscription.SetSubscriptionPolicy(subscriptionPolicy);

                    if (timeSpan == null)
                    {
                        topicSubscription.Expiration = TimeSpan.MaxValue.Ticks;
                    }
                    else
                    {
                        topicSubscription.Expiration = timeSpan.Value.Ticks;
                    }

                    Subscribe(topicSubscription, subscriptionPolicy);

                    lock (_subscriptions)
                    {
                        var existingSubscription = GetExistingSubscription(subscriptionIdentifier, subscriptionPolicy);

                        if (existingSubscription == null)
                        {
                            _subscriptions.Add(subscriptionIdentifier, topicSubscription);
                        }
                        else
                        {
                            return(existingSubscription);
                        }
                    }

                    _parent.OnSubscriptionCreated(this, topicSubscription);
                }
                return(topicSubscription);
            }
            finally
            {
                _readerWriterLock.ReleaseReaderLock();
            }
        }
Example #18
0
        public void Test_properties_from_selector_constructor()
        {
            // Arrange
            string filter     = @"{
                                ""LHS"": ""Foo"",
                                ""OP"": ""EQ"",
                                ""RHS"": ""bar""        
                              }";
            var    identifier = new SubscriptionIdentifier("foo", filter);

            // Assert
            Assert.That(identifier.Topic, Is.EqualTo("foo"));
            Assert.That(identifier.Filter, Is.EqualTo(filter));
            Assert.That(identifier.Selector, Is.EqualTo("Topic = 'foo' and " + filter));
        }
Example #19
0
        private TopicSubscription GetExistingSubscription(SubscriptionIdentifier subscriptionIdentifier, SubscriptionPolicyType subscriptionPolicy)
        {
            TopicSubscription topicSubscription = null;

            if (_subscriptions.TryGetValue(subscriptionIdentifier, out topicSubscription))
            {
                if ((subscriptionPolicy != SubscriptionPolicyType.EventSubscription))
                {
                    throw new OperationFailedException(ErrorCodes.PubSub.SUBSCRIPTION_EXISTS, ErrorMessages.GetErrorMessage(ErrorCodes.PubSub.SUBSCRIPTION_EXISTS));
                }
                else
                {
                    topicSubscription.UpdateCount();
                }
            }
            return(topicSubscription);
        }
        public async void Test_filter_doesnt_match()
        {
            // Arrange
            _mockFilterFactory.Setup(f => f.GetExpressionAsync("Topic = 'bar'"))
            .Returns(() => Task.FromResult(Mock.Of <IFilterExpression>(e => e.EvaluateAsync(It.IsAny <IReadOnlyDictionary <string, object> >()) == Task.FromResult <IComparable>(false))));
            var subscription  = new SubscriptionIdentifier("bar", null);
            var subscriptions = new[]
            {
                new KeyValuePair <SubscriptionIdentifier, MessageBusCallbackDelegate>(subscription,
                                                                                      (topic, filter, message) => { })
            };
            // Act
            var filterTask = await _filteringService.Filter(_messageContextMock.Object, subscriptions);

            // Assert
            Assert.That(filterTask.Any(p => p.Key == subscription), Is.False);
        }
Example #21
0
        public bool AddSubscription(SubscriptionInfo subscriptionInfo, SubscriptionIdentifier subscriptionIdentifier, bool isUserOperation = true)
        {
            Subscriptions subscription;
            bool          created = true;

            lock (_mutex)
            {
                if (_subscriptions.TryGetValue(subscriptionIdentifier, out subscription))
                {
                    if (subscription.SubscriptionPolicyType == SubscriptionPolicyType.NonDurableExclusiveSubscription && isUserOperation)
                    {
                        created = false;
                    }
                    else
                    {
                        if (subscriptionInfo.SubPolicyType != SubscriptionPolicyType.NonDurableExclusiveSubscription)
                        {
                            created = subscription.AddSubscriber(subscriptionInfo.ClientId);
                        }
                    }
                }
                else
                {
                    switch (subscriptionInfo.SubPolicyType)
                    {
                    case SubscriptionPolicyType.NonDurableExclusiveSubscription:
                        if (subscriptionInfo.Type != SubscriptionType.Publisher)
                        {
                            subscription = new ExclusiveSubscriptions(subscriptionInfo.ClientId, subscriptionInfo.SubscriptionId, subscriptionInfo.SubPolicyType, subscriptionInfo.Expiration, _context);
                        }
                        else
                        {
                            subscription = new ExclusiveSubscriptions(subscriptionInfo.ClientId, subscriptionInfo.SubscriptionId, subscriptionInfo.SubPolicyType, subscriptionInfo.Expiration, _context, subscriptionInfo.Type);
                        }
                        break;

                    case SubscriptionPolicyType.EventSubscription:
                        subscription = new EventSubscriptions(subscriptionInfo.ClientId, subscriptionInfo.SubscriptionId, subscriptionInfo.SubPolicyType, subscriptionInfo.Expiration, _context, subscriptionInfo.Type);
                        break;
                    }
                    _subscriptions.Add(subscriptionIdentifier, subscription);
                }
                return(created);
            }
        }
        public void Test_when_concurrent_subscribe_on_same_topic_should_callback_once()
        {
            //Arrange
            var count        = 0;
            var manualResets = Enumerable.Range(0, 10).Select(_ => new ManualResetEvent(false)).ToArray();
            var subscription = new SubscriptionIdentifier("foo", null);

            var testCallbackDelegates = new MessageBusCallbackDelegate[10];

            for (int i = 0; i < 10; i++)
            {
                testCallbackDelegates[i] = (topic, filter, message) =>
                {
                    Interlocked.Increment(ref count);
                    manualResets[i].Set();
                }
            }
            ;

            var mockMessage = new Mock <IMagicHubMessage>();

            _mockFilteringService
            .Setup(f =>
                   f.Filter(
                       It.IsAny <IReadOnlyDictionary <string, object> >(),
                       It.IsAny <IEnumerable <KeyValuePair <SubscriptionIdentifier, MessageBusCallbackDelegate> > >()))
            .Returns(Task.FromResult <IEnumerable <KeyValuePair <SubscriptionIdentifier, MessageBusCallbackDelegate> > >(new[]
            {
                new KeyValuePair <SubscriptionIdentifier, MessageBusCallbackDelegate>(
                    subscription,
                    (topic, filter, message) => Interlocked.Increment(ref count))
            }));

            //Act
            Enumerable.Range(0, 10).AsParallel().ForAll(i => _dispatcher.Subscribe(subscription, testCallbackDelegates[i]));

            _dispatcher.DispatchMessage(mockMessage.Object);
            WaitHandle.WaitAny(manualResets, 100);

            //Assert
            Assert.That(count, Is.EqualTo(1));
        }
    }
Example #23
0
        public void RevokeAssignment(MessageInfo messageInfo, SubscriptionInfo subscriptionInfo)
        {
            bool messageRequed = false;

            ClientSubscriptionManager client = null;

            lock (_mutex)
            {
                Message message = null;

                if (!_messages.TryGetValue(messageInfo.MessageId, out message))
                {
                    return;
                }

                if (subscriptionInfo == null)     //revoke all subscriptions
                {
                    message.MessageMetaData.RevokeSubscriptions();
                }
                else
                {
                    if (_subscribers.TryGetValue(subscriptionInfo.ClientId, out client))
                    {
                        message.MessageMetaData.RevokeSubscriptions(client);
                    }
                }

                SubscriptionIdentifier subscriptonId = null;
                if (subscriptionInfo != null)
                {
                    subscriptonId = new SubscriptionIdentifier();
                    subscriptonId.SubscriptionName   = subscriptionInfo.SubscriptionId;
                    subscriptonId.SubscriptionPolicy = subscriptionInfo.SubPolicyType;
                }

                messageRequed = RequeMessage(message, subscriptonId);
            }

            if (messageRequed && _listener != null)
            {
                _listener.OnMessageArrived(this);
            }
        }
Example #24
0
        public SubscriptionInfo GetSubscriberForAssignment(SubscriptionType type, OperationContext context)
        {
            lock (_mutex)
            {
                if (_subscriptionLoadBalancer.IsValid)
                {
                    SubscriptionIdentifier firstSelectedIdentifier = null;
                    SubscriptionIdentifier selectedIdentifier      = null;
                    Subscriptions          subscription;
                    SubscriptionInfo       subscriptionInfo = new SubscriptionInfo();

                    while (true)
                    {
                        selectedIdentifier = _subscriptionLoadBalancer.GetNext();

                        if (firstSelectedIdentifier != null && selectedIdentifier.Equals(firstSelectedIdentifier))
                        {
                            return(null);
                        }

                        if (firstSelectedIdentifier == null)
                        {
                            firstSelectedIdentifier = selectedIdentifier;
                        }

                        if (_subscriptions.TryGetValue(selectedIdentifier, out subscription))
                        {
                            if (subscription.GetSubscriptionType == type)
                            {
                                subscriptionInfo.ClientId       = GetActiveSubscriber(subscription);
                                subscriptionInfo.SubscriptionId = selectedIdentifier.SubscriptionName;
                                subscriptionInfo.SubPolicyType  = subscription.SubscriptionPolicyType;
                                subscriptionInfo.Type           = type;
                                return(subscriptionInfo);
                            }
                        }
                    }
                }
                return(null);
            }
        }
Example #25
0
        void RemoveSubscribers(SubscriptionIdentifier subscriptionIdentifier)
        {
            Subscriptions    subscriptions;
            SubscriptionInfo subscriptionInfo = new SubscriptionInfo();

            if (_subscriptions.TryGetValue(subscriptionIdentifier, out subscriptions))
            {
                List <string> subscriberList = subscriptions.GetSubscriberList();
                if (subscriberList.Count > 0 && subscriberList != null)
                {
                    subscriptionInfo.SubscriptionId = subscriptionIdentifier.SubscriptionName;
                    subscriptionInfo.SubPolicyType  = subscriptionIdentifier.SubscriptionPolicy;
                    subscriptionInfo.Type           = SubscriptionType.Subscriber;
                    foreach (var clientId in subscriberList)
                    {
                        subscriptionInfo.ClientId = clientId;
                        UnSubscribeSubscription(subscriptionInfo);
                    }
                }
            }
        }
Example #26
0
        public void OnSubscriptonRemoved(Message message, SubscriptionInfo subscriptionInfo)
        {
            bool messageRequed = false;
            SubscriptionIdentifier           subscriptionIdentifier     = new SubscriptionIdentifier(subscriptionInfo.SubscriptionId, subscriptionInfo.SubPolicyType);
            HashSet <SubscriptionIdentifier> subscriptionIdentifierList = new HashSet <SubscriptionIdentifier>();

            lock (_mutex)
            {
                message.MessageMetaData.RemoveFromReciepientList(subscriptionIdentifier);

                if (!_messages.TryGetValue(message.MessageId, out message))
                {
                    return;
                }

                messageRequed = RequeMessage(message, subscriptionIdentifier);
            }

            if (messageRequed && _listener != null)
            {
                _listener.OnMessageArrived(this);
            }
        }
        public void AddSubscription(SubscriptionInfo subscriptionInfo)
        {
            if (String.Compare(subscriptionInfo.ClientId, ClientID, StringComparison.OrdinalIgnoreCase) != 0)
            {
                return;
            }

            SubscriptionIdentifier subscriptionIdentifier = new SubscriptionIdentifier(subscriptionInfo.SubscriptionId, subscriptionInfo.SubPolicyType);

            lock (this)
            {
                _lastActivityTime = _updateTime = DateTime.Now;
                switch (subscriptionInfo.Type)
                {
                //add subscriptionIdentifier instead
                case Common.Enum.SubscriptionType.Subscriber:
                    if (!_messageSubscriptions.ContainsKey(subscriptionIdentifier))
                    {
                        _messageSubscriptions.Add(subscriptionIdentifier, new Subscribers(subscriptionInfo.SubscriptionId, subscriptionInfo.Type));
                        _messageSubscriptionLoadbalancer.Add(subscriptionIdentifier);
                        if (subscriptionInfo.ExpirationCheck())
                        {
                            _refreshSubscriptions.Add(subscriptionIdentifier);
                        }
                    }
                    break;

                case Common.Enum.SubscriptionType.Publisher:
                    if (!_deliverySubscriptions.ContainsKey(subscriptionIdentifier))
                    {
                        _deliverySubscriptions.Add(subscriptionIdentifier, new Subscribers(subscriptionInfo.SubscriptionId, subscriptionInfo.Type));
                        _deliverSubscriptionLoadbalancer.Add(subscriptionIdentifier);
                    }
                    break;
                }
            }
        }
Example #28
0
        /// <summary>
        ///     Unsubscribe all topics for connection
        /// </summary>
        /// <param name="connectionId">SignallR connection for which to unsubscribe</param>
        public async Task Unsubscribe(string connectionId)
        {
            await _subscriptionMutex.WaitAsync();

            Trace.TraceVerbose("Unsubscribe all. Entered Monitor. ConnectionId={0}", connectionId);

            try
            {
                List <string> selectorsToUnsubscribe;
                if (_subscribedSelectorsForConnection.TryRemove(connectionId, out selectorsToUnsubscribe))
                {
                    Trace.TraceVerbose("Unsubscribe all Removing all groups. ConnectionId={0}", connectionId);

                    foreach (var selector in selectorsToUnsubscribe)
                    {
                        var subscription = new SubscriptionIdentifier(selector);
                        await _messageBus.Unsubscribe(subscription.Topic, subscription.Filter);

                        _counters.NumberOfSubscriptionsTotal.Decrement();
                        Groups.Remove(connectionId, selector);
                    }
                    //await Task.WhenAll(
                    //    selectorsToUnsubscribe.Select((selector) => Groups.Remove(connectionId, selector)));
                    Trace.TraceVerbose("Unsubscribe all removed all groups. ConnectionId={0}", connectionId);
                }
            }
            catch (Exception exception)
            {
                //eat the exception as unsubscribe for connectionid need not be propogated as client is already disconnected.
                Trace.TraceError(exception);
            }
            finally
            {
                _subscriptionMutex.Release();
                Trace.TraceVerbose("Unsubscribe all released monitor. ConnectionId={0}", connectionId);
            }
        }
Example #29
0
        private bool AssignMessageToAllSubscriptions(SubscriptionInfo subscriptionInfo, Message message)
        {
            bool                      assigned = false;
            Subscriptions             subscriptions;
            ClientSubscriptionManager clientManager;

            lock (_mutex)
            {
                if (subscriptionInfo.SubPolicyType != SubscriptionPolicyType.EventSubscription)
                {
                    foreach (var subscription in _subscriptions)
                    {
                        HashSet <SubscriptionIdentifier> subscriptionIdentifierList;

                        if (subscription.Value.IsActive() && subscription.Value.SubscriptionPolicyType == SubscriptionPolicyType.NonDurableExclusiveSubscription)
                        {
                            string clientId = subscription.Value.GetSubscriber();
                            if (!String.IsNullOrEmpty(clientId))
                            {
                                if (_subscribers.TryGetValue(clientId, out clientManager))
                                {
                                    if (clientManager.HasMessageSubscriptons(SubscriptionType.Subscriber))
                                    {
                                        assigned |= clientManager.AssignMessageToSubscription(message, subscriptionInfo);
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (message.IsMulticast)
                    {
                        MultiCastMessage multicastMessage = (MultiCastMessage)message;
                        if (multicastMessage.SpecificReciepients.Count > 0 || multicastMessage.SpecificReciepients != null)
                        {
                            List <SubscriptionInfo> subinfolist = multicastMessage.SpecificReciepients;
                            foreach (var subInfo in subinfolist)
                            {
                                if (_subscribers.TryGetValue(subInfo.ClientId, out clientManager))
                                {
                                    assigned = clientManager.AssignMessageToSubscription(message, subscriptionInfo);
                                }
                            }
                        }
                    }
                    else
                    {
                        SubscriptionIdentifier subscriptionIdentifier = new SubscriptionIdentifier();
                        subscriptionIdentifier.SubscriptionName   = SubscriptionInfo.EventsSubscriptionName;
                        subscriptionIdentifier.SubscriptionPolicy = SubscriptionPolicyType.EventSubscription;
                        if (_subscriptions.TryGetValue(subscriptionIdentifier, out subscriptions))
                        {
                            List <string> subscribedClients = subscriptions.GetSubscriberList();
                            if (subscriptions.IsActive() && (subscribedClients.Count > 0))
                            {
                                foreach (var clientId in subscribedClients)
                                {
                                    if (_subscribers.TryGetValue(clientId, out clientManager))
                                    {
                                        if (clientManager.HasMessageSubscriptons(SubscriptionType.Subscriber))
                                        {
                                            assigned |= clientManager.AssignMessageToSubscription(message, subscriptionInfo);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(assigned);
        }
        public bool RemoveSubscription(SubscriptionInfo subscriptionInfo)
        {
            //use subscription IDentifier
            if (string.Compare(subscriptionInfo.ClientId, ClientID, true) != 0)
            {
                return(false);
            }

            SubscriptionIdentifier subscriptionIdentifier = new SubscriptionIdentifier(subscriptionInfo.SubscriptionId, subscriptionInfo.SubPolicyType);
            List <Message>         removedMessages        = new List <Message>();
            bool result = false;

            lock (this)
            {
                _lastActivityTime = _updateTime = DateTime.Now;
                switch (subscriptionInfo.Type)
                {
                case Common.Enum.SubscriptionType.Subscriber:
                    if (_messageSubscriptions.ContainsKey(subscriptionIdentifier))
                    {
                        result = _messageSubscriptions.Remove(subscriptionIdentifier);
                        _messageSubscriptionLoadbalancer.Remove(subscriptionIdentifier);
                    }
                    break;

                case Common.Enum.SubscriptionType.Publisher:
                    if (_deliverySubscriptions.ContainsKey(subscriptionIdentifier))
                    {
                        result = _deliverySubscriptions.Remove(subscriptionIdentifier);
                        _deliverSubscriptionLoadbalancer.Remove(subscriptionIdentifier);
                    }
                    break;
                }

                foreach (Message message in _messages.Values)
                {
                    if (message.MessageMetaData.DeliveryOption == Runtime.Caching.DeliveryOption.Any)
                    {
                        message.MessageMetaData.RemoveRecepient(subscriptionInfo.SubscriptionId);
                        message.MessageMetaData.RemoveFromReciepientList(subscriptionIdentifier);
                    }

                    message.MessageMetaData.UnregisterSubscription(this);
                    if (message.MessageMetaData.IsRemovable)
                    {
                        removedMessages.Add(message);
                    }
                }

                foreach (Message message in _delivryNotificationMessages.Values)
                {
                    message.MessageMetaData.UnregisterSubscription(this);
                    message.MessageMetaData.RemoveRecepient(subscriptionInfo.SubscriptionId);
                    message.MessageMetaData.RemoveFromReciepientList(subscriptionIdentifier);
                    if (message.MessageMetaData.IsRemovable)
                    {
                        removedMessages.Add(message);
                    }
                }
            }

            foreach (Message message in removedMessages)
            {
                if (message.MessageMetaData.SubscriptionType == Common.Enum.SubscriptionType.Publisher)
                {
                    _delivryNotificationMessages.Remove(message.MessageId);
                }
                else
                {
                    _messages.Remove(message.MessageId);
                }

                _topic.OnSubscriptonRemoved(message, subscriptionInfo);
            }
            _refreshSubscriptions.Remove(subscriptionIdentifier);
            return(result);
        }