Ejemplo n.º 1
0
        public async Task ConsumerCanPickUpWhereItLeftOff()
        {
            var receivedStrings = new ConcurrentQueue <string>();
            var topic           = BrokerFactory.GetNewTopic();

            var producer = BrokerFactory.ConfigureProducer()
                           .Topics(m => m.Map <string>(topic))
                           .Create();

            Using(producer);

            IDisposable CreateConsumer(InMemPositionsStorage storage)
            {
                return(BrokerFactory.ConfigureConsumer("default-group")
                       .Handle(async(messages, token) =>
                {
                    var strings = messages.Select(m => m.Body).Cast <string>();

                    receivedStrings.Enqueue(strings);
                })
                       .Topics(t => t.Subscribe(topic))
                       .Positions(p => p.StoreInMemory(storage))
                       .Start());
            }

            var positionsStorage = new InMemPositionsStorage();

            const string partitionKey = "same-every-time";

            using (CreateConsumer(positionsStorage))
            {
                await producer.Send("HEJ", partitionKey : partitionKey);

                await producer.Send("MED", partitionKey : partitionKey);

                await producer.Send("DIG", partitionKey : partitionKey);

                string GetFailureDetailsFunction() => $@"Got these strings:

{receivedStrings.ToPrettyJson()}";

                await receivedStrings.WaitOrDie(
                    completionExpression : q => q.Count == 3,
                    failExpression : q => q.Count > 3,
                    failureDetailsFunction : GetFailureDetailsFunction
                    );
            }

            Console.WriteLine($@"Got these positions after FIRST run:

{string.Join(Environment.NewLine, positionsStorage.GetAll(topic).Select(position => $"    {position}"))}

");

            using (CreateConsumer(positionsStorage))
            {
                await producer.Send("MIN", partitionKey : partitionKey);

                await producer.Send("SØDE", partitionKey : partitionKey);

                await producer.Send("VEN", partitionKey : partitionKey);

                await receivedStrings.WaitOrDie(q => q.Count == 6, failExpression : q => q.Count > 6);

                // additional delay to be absolutely sure that no additional messages arrive after this point
                await Task.Delay(TimeSpan.FromSeconds(1));
            }

            Console.WriteLine($@"Got these positions after SECOND run:

{string.Join(Environment.NewLine, positionsStorage.GetAll(topic).Select(position => $"    {position}"))}

");

            Assert.That(receivedStrings.Count, Is.EqualTo(6), $@"Queue did not contain 6 strings as expected:

{receivedStrings.ToPrettyJson()}");

            var expectedReceivedStrings = new[]
            {
                "HEJ",
                "MED",
                "DIG",
                "MIN",
                "SØDE",
                "VEN",
            };

            Assert.That(receivedStrings, Is.EqualTo(expectedReceivedStrings), $@"

Expected

    {string.Join(", ", expectedReceivedStrings)}

but got

    {string.Join(", ", receivedStrings)}

");
        }