/// <summary>
        /// Sends standard test sequence.
        /// </summary>
        /// <param name="producer">The producer.</param>
        private static async Task SendSequenceAsync(ISequenceOperations producer)
        {
            await producer.RegisterAsync(new User());

            await producer.LoginAsync("admin", "1234");

            await producer.EarseAsync(4335);
        }
        public async Task OnSucceed_ACK_Test()
        {
            #region ISequenceOperations producer = ...

            ISequenceOperations producer = _producerBuilder
                                           //.WithOptions(producerOption)
                                           .Partition(PARTITION)
                                           .Shard(SHARD)
                                           .WithLogger(_fakeLogger)
                                           .Build <ISequenceOperations>();

            #endregion // ISequenceOperations producer = ...

            await SendSequenceAsync(producer);

            var consumerOptions = new ConsumerOptions(
                AckBehavior.OnSucceed,
                maxMessages: 3 /* detach consumer after 3 messages*/);
            CancellationToken cancellation = GetCancellationToken();

            #region await using IConsumerLifetime subscription = ...Subscribe(...)

            await using IConsumerLifetime subscription = _consumerBuilder
                                                         .WithOptions(consumerOptions)
                                                         .WithCancellation(cancellation)
                                                         .Partition(PARTITION)
                                                         .Shard(SHARD)
                                                         .WithLogger(_fakeLogger)
                                                         .Subscribe(meta => _subscriber, "CONSUMER_GROUP_1", $"TEST {DateTime.UtcNow:HH:mm:ss}");

            #endregion // await using IConsumerLifetime subscription = ...Subscribe(...)

            await subscription.Completion;

            #region Validation

            A.CallTo(() => _subscriber.RegisterAsync(A <User> .Ignored))
            .MustHaveHappenedOnceExactly();
            A.CallTo(() => _subscriber.LoginAsync("admin", "1234"))
            .MustHaveHappenedOnceExactly();
            A.CallTo(() => _subscriber.EarseAsync(4335))
            .MustHaveHappenedOnceExactly();

            #endregion // Validation
        }
 /// <summary>
 /// Initializes a new instance of the SharedSequenceLogic class.
 /// </summary>
 /// <param name="context">
 /// The context of the current API call.
 /// </param>
 /// <param name="sequenceOperations">
 /// The object to use to perform operations on sequences.
 /// </param>
 public SharedSequenceLogic(CommerceContext context,
                            ISequenceOperations sequenceOperations)
 {
     Context            = context;
     SequenceOperations = sequenceOperations;
 }
        public async Task Claim_Test()
        {
            ISequenceOperations otherSubscriber = A.Fake <ISequenceOperations>();

            #region ISequenceOperations producer = ...

            ISequenceOperations producer = _producerBuilder
                                           //.WithOptions(producerOption)
                                           .Partition(PARTITION)
                                           .Shard(SHARD)
                                           .Build <ISequenceOperations>();

            #endregion // ISequenceOperations producer = ...

            #region A.CallTo(...).ReturnsLazily(...)

            A.CallTo(() => otherSubscriber.RegisterAsync(A <User> .Ignored))
            .ReturnsLazily <ValueTask>(() =>
            {
                throw new ApplicationException("test intensional exception");
            });
            A.CallTo(() => otherSubscriber.LoginAsync(A <string> .Ignored, A <string> .Ignored))
            .ReturnsLazily(() => ValueTaskStatic.CompletedValueTask);
            A.CallTo(() => otherSubscriber.EarseAsync(A <int> .Ignored))
            .ReturnsLazily(() => ValueTaskStatic.CompletedValueTask);

            #endregion // A.CallTo(...).ReturnsLazily(...)

            await SendSequenceAsync(producer);

            var consumerOptions = new ConsumerOptions(
                AckBehavior.OnSucceed,
                maxMessages: 3 /* detach consumer after 3 messages */);
            CancellationToken cancellation = GetCancellationToken();

            #region await using IConsumerLifetime subscription = ...Subscribe(...)

            var consumerPipe = _consumerBuilder
                               .WithOptions(consumerOptions)
                               .WithCancellation(cancellation)
                               .Partition(PARTITION)
                               .Shard(SHARD)
                               .WithResiliencePolicy(Policy.Handle <Exception>().RetryAsync(3))
                               .WithLogger(_fakeLogger);

            await using IConsumerLifetime otherSubscription = consumerPipe
                                                              .Subscribe(meta => otherSubscriber, "CONSUMER_GROUP_1", $"TEST Other {DateTime.UtcNow:HH:mm:ss}");

            await otherSubscription.Completion;

            await using IConsumerLifetime subscription = consumerPipe
                                                         .Subscribe(meta => _subscriber, "CONSUMER_GROUP_1", $"TEST {DateTime.UtcNow:HH:mm:ss}");

            #endregion // await using IConsumerLifetime subscription = ...Subscribe(...)

            await subscription.Completion;

            #region Validation

            A.CallTo(() => otherSubscriber.RegisterAsync(A <User> .Ignored))
            .MustHaveHappened(
                (3 /* Polly retry */ + 1 /* throw */) * 3 /* disconnect after 3 messaged */,
                Times.Exactly);
            A.CallTo(() => _subscriber.RegisterAsync(A <User> .Ignored))
            .MustHaveHappenedOnceExactly();
            A.CallTo(() => _subscriber.LoginAsync("admin", "1234"))
            .MustHaveHappenedOnceExactly();
            A.CallTo(() => _subscriber.EarseAsync(4335))
            .MustHaveHappenedOnceExactly();

            #endregion // Validation
        }
        public async Task Resilience_Test()
        {
            #region ISequenceOperations producer = ...

            ISequenceOperations producer = _producerBuilder
                                           //.WithOptions(producerOption)
                                           .Partition(PARTITION)
                                           .Shard(SHARD)
                                           .Build <ISequenceOperations>();

            #endregion // ISequenceOperations producer = ...

            int tryNumber = 0;
            A.CallTo(() => _subscriber.RegisterAsync(A <User> .Ignored))
            .ReturnsLazily(() => Ack.Current.AckAsync());
            A.CallTo(() => _subscriber.LoginAsync(A <string> .Ignored, A <string> .Ignored))
            .ReturnsLazily <ValueTask>(async() =>
            {
                if (Interlocked.Increment(ref tryNumber) == 1)
                {
                    throw new ApplicationException("test intensional exception");
                }

                await Ack.Current.AckAsync();
            });
            A.CallTo(() => _subscriber.EarseAsync(A <int> .Ignored))
            .ReturnsLazily(() => Ack.Current.AckAsync());


            await SendSequenceAsync(producer);

            var consumerOptions = new ConsumerOptions(
                AckBehavior.Manual,
                maxMessages: 3 /* detach consumer after 3 messages */);
            CancellationToken cancellation = GetCancellationToken();

            #region await using IConsumerLifetime subscription = ...Subscribe(...)

            await using IConsumerLifetime subscription = _consumerBuilder
                                                         .WithOptions(consumerOptions)
                                                         .WithCancellation(cancellation)
                                                         .Partition(PARTITION)
                                                         .Shard(SHARD)
                                                         .WithResiliencePolicy(Policy.Handle <Exception>().RetryAsync(3))
                                                         .WithLogger(_fakeLogger)
                                                         .Subscribe(meta => _subscriber, "CONSUMER_GROUP_1", $"TEST {DateTime.UtcNow:HH:mm:ss}");

            #endregion // await using IConsumerLifetime subscription = ...Subscribe(...)

            await subscription.Completion;

            #region Validation

            A.CallTo(() => _subscriber.RegisterAsync(A <User> .Ignored))
            .MustHaveHappenedOnceExactly();
            A.CallTo(() => _subscriber.LoginAsync("admin", "1234"))
            .MustHaveHappenedTwiceExactly();             /* 1 Polly, 1 succeed */
            A.CallTo(() => _subscriber.EarseAsync(4335))
            .MustHaveHappenedOnceExactly();

            #endregion // Validation
        }
        public async Task Manual_ACK_Test()
        {
            #region ISequenceOperations producer = ...

            ISequenceOperations producer = _producerBuilder
                                           //.WithOptions(producerOption)
                                           .Partition(PARTITION)
                                           .Shard(SHARD)
                                           .Build <ISequenceOperations>();

            #endregion // ISequenceOperations producer = ...

            #region A.CallTo(...).ReturnsLazily(...)


            int tryNumber = 0;
            A.CallTo(() => _subscriber.RegisterAsync(A <User> .Ignored))
            .ReturnsLazily(() => Ack.Current.AckAsync());
            A.CallTo(() => _subscriber.LoginAsync(A <string> .Ignored, A <string> .Ignored))
            .ReturnsLazily <ValueTask>(async() =>
            {
                // 3 error will be catch by Polly, the 4th one will catch outside of Polly
                if (Interlocked.Increment(ref tryNumber) < 5)
                {
                    throw new ApplicationException("test intensional exception");
                }

                await Ack.Current.AckAsync();
            });
            A.CallTo(() => _subscriber.EarseAsync(A <int> .Ignored))
            .ReturnsLazily(() => Ack.Current.AckAsync());

            #endregion // A.CallTo(...).ReturnsLazily(...)


            await SendSequenceAsync(producer);

            var consumerOptions = new ConsumerOptions(
                AckBehavior.Manual,
                maxMessages: 4 /* detach consumer after 4 messages*/);
            CancellationToken cancellation = GetCancellationToken();

            #region await using IConsumerLifetime subscription = ...Subscribe(...)

            await using IConsumerLifetime subscription = _consumerBuilder
                                                         .WithOptions(consumerOptions)
                                                         .WithCancellation(cancellation)
                                                         .Partition(PARTITION)
                                                         .Shard(SHARD)
                                                         .WithResiliencePolicy(Policy.Handle <Exception>().RetryAsync(3, (ex, i) => _outputHelper.WriteLine($"Retry {i}")))
                                                         .WithLogger(_fakeLogger)
                                                         .Subscribe(meta => _subscriber, "CONSUMER_GROUP_1", $"TEST {DateTime.UtcNow:HH:mm:ss}");

            #endregion // await using IConsumerLifetime subscription = ...Subscribe(...)

            await subscription.Completion;

            #region Validation

            A.CallTo(() => _subscriber.RegisterAsync(A <User> .Ignored))
            .MustHaveHappenedOnceExactly();
            A.CallTo(() => _subscriber.LoginAsync("admin", "1234"))
            .MustHaveHappened(
                3 /* Polly retry */ + 1 /* error */ + 1 /* succeed */,
                Times.Exactly);
            A.CallTo(() => _subscriber.EarseAsync(4335))
            .MustHaveHappenedOnceExactly();

            #endregion // Validation
        }