示例#1
0
        public void RetryOnVisibilityTimeout()
        {
            // Arrange
            var topicName = "Ordered.VisibilityTimemout";
            var subName   = topicName + "_Sub1";
            var topic     = _publisher.AddOrUpdateTopic(new Topic {
                Name = topicName
            });
            var sub1 = _consumer.AddOrUpdateSubscription(new Subscription
            {
                Name               = subName,
                Ordered            = true,
                DeliveryDelay      = 1,
                TimeToLive         = 60,
                MaxDeliveries      = 0,
                TopicSubscriptions = new List <TopicSubscription> {
                    new TopicSubscription {
                        TopicId = topic.Id.Value, Enabled = true
                    }
                },
            });

            var publishedDateUtcBaseLine = DateTime.UtcNow.AddSeconds(-10); // Explicitly setting publicationdates to make sure none are the same!

            _publisher.Publish(topicName, payload: "1", functionalKey: "1", publicationDateUtc: publishedDateUtcBaseLine.AddSeconds(1));
            _publisher.Publish(topicName, payload: "2", functionalKey: "1", publicationDateUtc: publishedDateUtcBaseLine.AddSeconds(2));

            var visibilityTimeout = 1;
            var e = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault();

            Assert.Equal("1", e.Payload);
            e = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault();
            Assert.Null(e); // event(payload) 2 has same functional key and should not be delivered yet

            // Try several times to make sure we don't run into race conditions
            for (int attempt = 0; attempt < 20; attempt++)
            {
                // Now wait until p1 expires
                do
                {
                    Thread.Sleep(2); // Not too long
                    e = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault();
                } while (e == null);
                Assert.Equal("1", e.Payload); // p1 should be delivered once again!
            }

            // Now mark it consumed and get the next event
            _consumer.MarkConsumed(e.Id, e.DeliveryKey); // p1 should be gone, so p2 can be delivered
            e = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault();
            Assert.Equal("2", e.Payload);                // p2 should now be delivered, since p1 has been consumed on the second attempt
        }
示例#2
0
        public void Expiration()
        {
            // Arrange
            var topicName = "HousekeepingTests.Expiration";
            var subName   = topicName + "_Sub1";
            var topic     = _publisher.AddOrUpdateTopic(new Topic {
                Name = topicName
            });
            var sub1 = _consumer.AddOrUpdateSubscription(new Subscription
            {
                Name = subName,
                TopicSubscriptions = new List <TopicSubscription> {
                    new TopicSubscription {
                        TopicId = topic.Id.Value, Enabled = true
                    }
                },
            });

            var utcNow = DateTime.UtcNow;

            _publisher.Publish(topicName, eventName: topicName + "1", expirationDateUtc: utcNow.AddSeconds(5), payload: "1");
            _publisher.Publish(topicName, eventName: topicName + "2", expirationDateUtc: utcNow.AddSeconds(5), payload: "2");
            _publisher.Publish(topicName, eventName: topicName + "3", expirationDateUtc: utcNow.AddMinutes(15), payload: "3");

            var visibilityTimeout = 1;                                                         // Must expire asap
            var ce1 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault();
            var ce2 = _consumer.ConsumeNext(subName, visibilityTimeout: 10).SingleOrDefault(); // Still invisible after expiration
            var ce3 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault();

            Assert.Equal("1", ce1.Payload); // Not yet expired
            Assert.Equal("2", ce2.Payload);
            Assert.Equal("3", ce3.Payload);
            Thread.Sleep(TimeSpan.FromSeconds(5 + 1));

            _consumer.PerformHouseKeepingTasks();

            // Check that only 1 se in table
            var eventNames = _fixture.GetEventNamesForFailedEvents(sub1.Id.Value);

            Assert.Equal(1, eventNames.Count);
            Assert.Equal(topicName + "1", eventNames.First());
            // 2 has expired, but is still invisible, so may still be processed
        }
示例#3
0
        public void VisibilityTimeout()
        {
            // Arrange
            var topicName = "Consuming.BasicTests.VisibilityTimeout";
            var subName   = topicName + "_Sub1";
            var topic     = _publisher.AddOrUpdateTopic(new Topic {
                Name = topicName
            });
            var sub1 = _consumer.AddOrUpdateSubscription(new Subscription
            {
                Name = subName,
                TopicSubscriptions = new List <TopicSubscription> {
                    new TopicSubscription {
                        TopicId = topic.Id.Value, Enabled = true
                    }
                },
            });

            _publisher.Publish(topicName);

            var visibilityTimeout = 2;
            var ce1 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault();

            Assert.NotNull(ce1);
            var ce2 = _consumer.ConsumeNext(subName).SingleOrDefault();

            Assert.Null(ce2);                                          // Locked, so should not be returned.

            Thread.Sleep(TimeSpan.FromSeconds(visibilityTimeout + 1)); // Wait until visibilitytimeout has expired
            ce2 = _consumer.ConsumeNext(subName).SingleOrDefault();
            Assert.NotNull(ce2);                                       // Should be unlocked again
        }
示例#4
0
        public void DeleteTopic()
        {
            // Arrange
            var topicName = "Publishing.TopicTests.DeleteTopic";
            var topicNotes = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";

            // Act
            var addedTopic = _publisher.AddOrUpdateTopic(new Topic { Name = topicName, Notes = topicNotes });
            _publisher.DeleteTopic(addedTopic.Id.Value, true);

            // Assert
            Assert.Null(_publisher.GetTopic(addedTopic.Id.Value));

            // Act
            var addedTopicWithSubscriptions = _publisher.AddOrUpdateTopic(new Topic { Name = topicName + "_WithSubs", Notes = topicNotes });
            var sub1 = _consumer.AddOrUpdateSubscription(new Subscription
            {
                Name = addedTopicWithSubscriptions.Name + "_Sub1",
                TopicSubscriptions = new List<TopicSubscription>
                {
                    new TopicSubscription
                    {
                        TopicId = addedTopicWithSubscriptions.Id.Value, Enabled = true, Filtered = true,
                        Filters = new List<TopicSubscriptionFilter>
                        {
                            new TopicSubscriptionFilter { Header = "EventType", MatchExpression = "Order.*" },
                        },
                    },
                },
            });
            _publisher.Publish(addedTopicWithSubscriptions.Name, payload: "test"); // Make sure there are also TopicEvents and SubscriptionEvents

            // Assert/act
            Assert.ThrowsAny<Exception>(() => _publisher.DeleteTopic(addedTopicWithSubscriptions.Id.Value, false));
            Assert.NotNull(_publisher.GetTopic(addedTopicWithSubscriptions.Id.Value));

            // Act
            _publisher.DeleteTopic(addedTopicWithSubscriptions.Id.Value, true);

            // Assert
            Assert.Null(_publisher.GetTopic(addedTopicWithSubscriptions.Id.Value));

            // Delete non-existing (should not fail)
            _publisher.DeleteTopic(addedTopicWithSubscriptions.Id.Value, true);
        }
        public void PublicationDate_Default()
        {
            // Arrange
            var topicName = "StandardOrderingTests.PublicationDate_Default";
            var subName   = topicName + "_Sub1";
            var topic     = _publisher.AddOrUpdateTopic(new Topic {
                Name = topicName
            });
            var sub1 = _consumer.AddOrUpdateSubscription(new Subscription
            {
                Name = subName, // When ordered not set, delivery should still be ordered on publicationdateutc
                TopicSubscriptions = new List <TopicSubscription> {
                    new TopicSubscription {
                        TopicId = topic.Id.Value, Enabled = true
                    }
                },
            });

            _publisher.Publish(topicName, payload: "1");
            Thread.Sleep(100); // To make sure publicationdateutc is not equal for each item
            _publisher.Publish(topicName, payload: "2");
            Thread.Sleep(100);
            _publisher.Publish(topicName, payload: "3");

            var visibilityTimeout = 2;
            var ce1 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault();
            var ce2 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault();
            var ce3 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault();

            Assert.Equal("1", ce1.Payload);
            Assert.Equal("2", ce2.Payload);
            Assert.Equal("3", ce3.Payload);
            _consumer.MarkConsumed(ce2.Id, ce2.DeliveryKey);           // ce2 should be gone

            Thread.Sleep(TimeSpan.FromSeconds(visibilityTimeout + 1)); // Wait until visibilitytimeout of all items (+1) has expired
            ce1 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault();
            ce3 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault();
            Assert.Equal("1", ce1.Payload);
            Assert.Equal("3", ce3.Payload);
        }
示例#6
0
        public void PublishComplete()
        {
            // Arrange
            var topicName = "Publishing.PublishTests.PublishComplete";
            var topic     = _publisher.AddOrUpdateTopic(new Topic {
                Name = topicName
            });
            var sub = _consumer.AddOrUpdateSubscription(new Subscription
            {
                Name = Guid.NewGuid().ToString(),
                TopicSubscriptions = new List <TopicSubscription> {
                    new TopicSubscription {
                        TopicId = topic.Id.Value, Enabled = true,
                    }
                }
            });

            var publicationDateUtc = DateTime.UtcNow.AddMinutes(1); // Overriding default (which is UtcNow)
            var expirationDateUtc  = DateTime.UtcNow.AddMinutes(5);
            var eventName          = "Name of the Event";
            var functionalKey      = "F1";
            var priority           = 10;
            var headers            = new Dictionary <string, string>
            {
                { "EventName", "Order.Purchased" },
                { "MessageId", Guid.NewGuid().ToString() },
            };
            var payload = "Hello";

            // Act
            var topicEvent = _publisher.Publish(topicName,
                                                eventName: eventName,
                                                publicationDateUtc: publicationDateUtc,
                                                expirationDateUtc: expirationDateUtc,
                                                functionalKey: functionalKey,
                                                priority: priority,
                                                headers: headers,
                                                payload: payload);

            // Assert
            Assert.NotNull(topicEvent.Id);
            Assert.Equal(topic.Id.Value, topicEvent.TopicId);
            Assert.Equal(eventName, topicEvent.EventName);
            Assert.Equal(publicationDateUtc, topicEvent.PublicationDateUtc);
            Assert.Equal(expirationDateUtc, topicEvent.ExpirationDateUtc);
            Assert.Equal(functionalKey, topicEvent.FunctionalKey);
            Assert.Equal(priority, topicEvent.Priority);
            Assert.NotNull(topicEvent.Headers);
            Assert.Equal(headers.Count, topicEvent.Headers.Count);
            Assert.True(headers.All(h => topicEvent.Headers.Any(teH => teH.Key == h.Key)));
            Assert.True(headers.All(h => h.Value == topicEvent.Headers[h.Key]));
            Assert.NotNull(topicEvent.PayloadId); // Cannot check payload here

            // Act
            var consumableEvent = _consumer.ConsumeNext(sub.Name).SingleOrDefault();

            // Assert
            Assert.NotNull(consumableEvent);
            Assert.NotNull(consumableEvent.Id);
            Assert.Equal(eventName, consumableEvent.EventName);
            Assert.Equal(functionalKey, consumableEvent.FunctionalKey);
            Assert.Equal(payload, consumableEvent.Payload);
            // Other properties do not exist on an consumable event
        }
示例#7
0
        public void SubscriptionStatistics()
        {
            // Arrange
            var topicName = "SubStats";
            var subName   = topicName + "_Sub1";
            var topic     = _publisher.AddOrUpdateTopic(new Topic {
                Name = topicName
            });
            var sub1 = _consumer.AddOrUpdateSubscription(new Subscription
            {
                Name               = subName,
                Ordered            = true,
                MaxDeliveries      = 1,
                TopicSubscriptions = new List <TopicSubscription> {
                    new TopicSubscription {
                        TopicId = topic.Id.Value, Enabled = true
                    }
                },
            });

            var utcNow  = DateTime.UtcNow;
            var funcKey = "A";

            // Create situation: failed-other (marked)
            _publisher.Publish(topicName, eventName: topicName + "0", functionalKey: funcKey);
            var ce = _consumer.ConsumeNext(sub1.Name).SingleOrDefault();

            _consumer.MarkFailed(ce.Id, ce.DeliveryKey, Reason.Other("Some other reason"));
            // Create situation: expired
            _publisher.Publish(topicName, eventName: topicName + "1", functionalKey: funcKey, expirationDateUtc: utcNow);
            Thread.Sleep(TimeSpan.FromSeconds(1)); // Expired for sure
            // Create situation: maxDeliveriesReached
            _publisher.Publish(topicName, eventName: topicName + "2", functionalKey: funcKey);
            ce = _consumer.ConsumeNext(sub1.Name, visibilityTimeout: 1).SingleOrDefault();
            Assert.Equal(topicName + "2", ce.EventName);
            Thread.Sleep(TimeSpan.FromSeconds(1 + 1)); // Becomes visible again, but has reached maxDeliveries
            // Create situation: overtaken
            _publisher.Publish(topicName, eventName: topicName + "3", functionalKey: funcKey, publicationDateUtc: utcNow.AddSeconds(2));
            ce = _consumer.ConsumeNext(sub1.Name).SingleOrDefault();
            Assert.Equal(topicName + "3", ce.EventName);
            _publisher.Publish(topicName, eventName: topicName + "4", functionalKey: funcKey, publicationDateUtc: utcNow.AddSeconds(-1));
            _consumer.MarkConsumed(ce.Id, ce.DeliveryKey); // #4 is now overtaken
            _publisher.Publish(topicName, eventName: topicName + "5", functionalKey: funcKey);

            var statsBeforeHouseKeeping = _consumer.GetSubscriptionStatistics(utcNow.AddMinutes(-10), utcNow.AddMinutes(+10));

            Assert.Equal(statsBeforeHouseKeeping.Single(s => s.Subscription.Id.Value == sub1.Id).Open, 4); // 4 open, since housekeeping has not yet moved them (3) to failed
            Assert.Equal(statsBeforeHouseKeeping.Single(s => s.Subscription.Id.Value == sub1.Id).Consumed, 1);
            Assert.Equal(statsBeforeHouseKeeping.Single(s => s.Subscription.Id.Value == sub1.Id).FailedExpired, 0);
            Assert.Equal(statsBeforeHouseKeeping.Single(s => s.Subscription.Id.Value == sub1.Id).FailedMaxDeliveriesReached, 0);
            Assert.Equal(statsBeforeHouseKeeping.Single(s => s.Subscription.Id.Value == sub1.Id).FailedOvertaken, 0);
            Assert.Equal(statsBeforeHouseKeeping.Single(s => s.Subscription.Id.Value == sub1.Id).FailedOther, 1); // Does not need housekeeping to move it
            _consumer.PerformHouseKeepingTasks();
            var statsAfterHouseKeeping = _consumer.GetSubscriptionStatistics(utcNow.AddMinutes(-10), utcNow.AddMinutes(+10));

            Assert.Equal(statsAfterHouseKeeping.Single(s => s.Subscription.Id.Value == sub1.Id).Open, 1);
            Assert.Equal(statsAfterHouseKeeping.Single(s => s.Subscription.Id.Value == sub1.Id).Consumed, 1);
            Assert.Equal(statsAfterHouseKeeping.Single(s => s.Subscription.Id.Value == sub1.Id).FailedExpired, 1);
            Assert.Equal(statsAfterHouseKeeping.Single(s => s.Subscription.Id.Value == sub1.Id).FailedMaxDeliveriesReached, 1);
            Assert.Equal(statsAfterHouseKeeping.Single(s => s.Subscription.Id.Value == sub1.Id).FailedOvertaken, 1);
            Assert.Equal(statsAfterHouseKeeping.Single(s => s.Subscription.Id.Value == sub1.Id).FailedOther, 1);
        }