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 ConsumeBatch_NotAllConsumed() { // Arrange var topicName = "ConsumeBatch_NotAllConsumed"; 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"); // Consume a batch of 2 items var batchSize = 2; var visibilityTimeout = 2; // 2 secs var ces = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout, maxCount: batchSize); Assert.Equal(batchSize, ces.Count()); Assert.True(ces.Any(ce => ce.Payload == "1")); Assert.True(ces.Any(ce => ce.Payload == "2")); // Mark only 2 consumed var ce1 = ces.Single(ce => ce.Payload == "1"); _consumer.MarkFailed(ce1.Id, ce1.DeliveryKey, Reason.Other("Fail")); _consumer.MarkConsumed(ces.Where(ce => ce.Payload == "2").Cast <ConsumableEventId>()); // Check if they are really marked consumed (can no longer be consumed) Thread.Sleep(TimeSpan.FromSeconds(visibilityTimeout + 1)); // Wait until visibilitytimeout of all items (+1) has expired ces = _consumer.ConsumeNext(subName, maxCount: batchSize); // Batchsize exceeds nr of events available Assert.Equal(1, ces.Count()); Assert.True(ces.Any(ce => ce.Payload == "3")); }
public void SerialDelivery() { // Arrange var topicName = "FunctionalOrderingTests.SerialDelivery"; var subName = topicName + "_Sub1"; // Substring to prevent too long sub-names var topic = _publisher.AddOrUpdateTopic(new Topic { Name = topicName }); var sub1 = _consumer.AddOrUpdateSubscription(new Subscription { Name = subName, Ordered = true, MaxDeliveries = 2, TopicSubscriptions = new List <TopicSubscription> { new TopicSubscription { TopicId = topic.Id.Value, Enabled = true } }, }); var publishedDateUtcBaseLine = DateTime.UtcNow.AddSeconds(-60); // Explicitly setting publicationdates to make sure none are the same! _publisher.Publish(topicName, payload: "1", functionalKey: "f1", publicationDateUtc: publishedDateUtcBaseLine.AddSeconds(1)); _publisher.Publish(topicName, payload: "2", functionalKey: "f1", publicationDateUtc: publishedDateUtcBaseLine.AddSeconds(2)); _publisher.Publish(topicName, payload: "3", functionalKey: "f2", publicationDateUtc: publishedDateUtcBaseLine.AddSeconds(3)); _publisher.Publish(topicName, payload: "4", functionalKey: "f1", publicationDateUtc: publishedDateUtcBaseLine.AddSeconds(4)); _publisher.Publish(topicName, payload: "5", functionalKey: "f2", publicationDateUtc: publishedDateUtcBaseLine.AddSeconds(5)); var visibilityTimeout = 5; var p1 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault(); // p1 stands for payload "1" var p3 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault(); var p2 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault(); Assert.Equal("1", p1.Payload); Assert.Equal("3", p3.Payload); Assert.Null(p2); // p(ayload) 2 has same functional key as p1 and should not be delivered yet _consumer.MarkConsumed(p1.Id, p1.DeliveryKey); // p1 should be gone, so p2 can be delivered p2 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault(); var p4 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault(); Assert.Equal("2", p2.Payload); Assert.Null(p4); // Again: same functional key as p2, so should not be delivered (and p3 is still locked) Thread.Sleep(TimeSpan.FromSeconds(visibilityTimeout + 1)); // Wait until visibilitytimeout of all items has expired p2 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault(); p3 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault(); p4 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault(); Assert.Equal("2", p2.Payload); // p2 should be redelivered, since it had expired Assert.Equal("3", p3.Payload); // p3 should be redelivered, since it had expired Assert.Null(p4); // p4 still has same functional key as p2, so should not be delivered _consumer.MarkFailed(p2.Id, p2.DeliveryKey, Reason.Other("test")); p4 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault(); Assert.Equal("4", p4.Payload); Thread.Sleep(TimeSpan.FromSeconds(visibilityTimeout + 1)); // Wait until visibilitytimeout of all items has expired p4 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault(); var p5 = _consumer.ConsumeNext(subName, visibilityTimeout: visibilityTimeout).SingleOrDefault(); Assert.Equal("4", p4.Payload); // p4 should be redeliverd (it was only delivered once) Assert.Equal("5", p5.Payload); // p3 has reached maxDeliveries, so p5 should now be delivered }
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); }