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 }
public void PublishNoLog() { // Arrange var topicName = "Publishing.PublishTests.PublishNoLog"; var topic = _publisher.AddOrUpdateTopic(new Topic { Name = topicName, Log = false }); var sub = _consumer.AddOrUpdateSubscription(new Subscription { Name = Guid.NewGuid().ToString(), TopicSubscriptions = new List <TopicSubscription> { new TopicSubscription { TopicId = topic.Id.Value, Enabled = true, } } }); // Act var topicEvent = _publisher.Publish(topicName); Thread.Sleep(TimeSpan.FromMilliseconds(200)); // To make sure that DateTime.UtcNow returns a later datetime than during the Publish-call // Assert Assert.Null(topicEvent.Id); Assert.Null(topicEvent.EventName); Assert.Equal(topic.Id.Value, topicEvent.TopicId); Assert.NotNull(topicEvent.PublicationDateUtc); Assert.True(topicEvent.PublicationDateUtc < DateTime.UtcNow); // Older than now Assert.True(topicEvent.PublicationDateUtc > DateTime.UtcNow.AddMinutes(-1)); // Less than a minute old Assert.Equal(MaxDateTime, topicEvent.ExpirationDateUtc); Assert.Equal(string.Empty, topicEvent.FunctionalKey); Assert.Equal(100, topicEvent.Priority); Assert.Null(topicEvent.Headers); Assert.Null(topicEvent.PayloadId); // Act var consumableEvent = _consumer.ConsumeNext(sub.Name).SingleOrDefault(); // Assert Assert.NotNull(consumableEvent); Assert.NotNull(consumableEvent.Id); Assert.Null(consumableEvent.EventName); Assert.Equal(string.Empty, consumableEvent.FunctionalKey); Assert.Null(consumableEvent.Payload); // Other properties do not exist on an consumable event // Consume it, to make sure the missing topicEvent is not a problem _consumer.MarkConsumed(consumableEvent.Id, consumableEvent.DeliveryKey); }
public void NoLog() { // Arrange var topicName = "Consuming.BasicTests.NoLog"; var subName = topicName + "_Sub1"; var topic = _publisher.AddOrUpdateTopic(new Topic { Name = topicName, Log = false }); // Log-flag should not matter, but just for sure var sub1 = _consumer.AddOrUpdateSubscription(new Subscription { Name = subName, LogConsumed = false, LogFailed = false, TopicSubscriptions = new List <TopicSubscription> { new TopicSubscription { TopicId = topic.Id.Value, Enabled = true } }, }); _publisher.Publish(topicName); _publisher.Publish(topicName); var ce1 = _consumer.ConsumeNext(subName).SingleOrDefault(); Assert.NotNull(ce1); _consumer.MarkConsumed(ce1.Id, ce1.DeliveryKey); var ce2 = _consumer.ConsumeNext(subName).SingleOrDefault(); Assert.NotNull(ce2); _consumer.MarkFailed(ce2.Id, ce2.DeliveryKey, Reason.Other("Whatever reason")); }
public void Overtaken() { // Arrange var topicName = "HousekeepingTests.Overtaken"; var subName = topicName + "_Sub1"; var topic = _publisher.AddOrUpdateTopic(new Topic { Name = topicName }); var sub1 = _consumer.AddOrUpdateSubscription(new Subscription { Name = subName, Ordered = true, TopicSubscriptions = new List <TopicSubscription> { new TopicSubscription { TopicId = topic.Id.Value, Enabled = true } }, }); var utcNow = DateTime.UtcNow; var funcKey = "A"; _publisher.Publish(topicName, eventName: topicName + "1", publicationDateUtc: utcNow, functionalKey: funcKey); var ce = _consumer.ConsumeNext(subName).SingleOrDefault(); _consumer.MarkConsumed(ce.Id, ce.DeliveryKey); _publisher.Publish(topicName, eventName: topicName + "2", publicationDateUtc: utcNow.AddSeconds(-1), functionalKey: funcKey); ce = _consumer.ConsumeNext(subName).SingleOrDefault(); Assert.Null(ce); // Already overtaken, so should not be delivered _consumer.PerformHouseKeepingTasks(); // Check that only 1 se in table var eventNames = _fixture.GetEventNamesForFailedEvents(sub1.Id.Value); Assert.Equal(1, eventNames.Count); Assert.Equal(topicName + "2", eventNames.First()); }
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); }
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); }