private Envelope RestoreEnvelope(PendingCommand command) =>
 new Envelope(
     command.MessageId,
     _serializer.Deserialize(command.CommandJson),
     operationId: command.OperationId,
     correlationId: command.CorrelationId,
     contributor: command.Contributor);
Example #2
0
        private void InsertPendingCommands(T processManager, string operationId, Guid?correlationId, string contributor)
        {
            IEnumerable <PendingCommand> pendingCommands = processManager
                                                           .FlushPendingCommands()
                                                           .Select(command => new Envelope(Guid.NewGuid(), command, operationId, correlationId, contributor))
                                                           .Select(envelope => PendingCommand.FromEnvelope(processManager, envelope, _serializer));

            _dbContext.PendingCommands.AddRange(pendingCommands);
        }
        public async Task FlushCommands_sends_all_commands_associated_with_specified_process_manager_sequentially()
        {
            // Arrange
            var serializer = new JsonMessageSerializer();

            var processManager      = new FakeProcessManager();
            var noiseProcessManager = new FakeProcessManager();

            var random  = new Random();
            var fixture = new Fixture();

            var envelopes = new List <Envelope>(
                from command in new[]
            {
                new FakeCommand {
                    Int32Value = random.Next(), StringValue = fixture.Create <string>()
                },
                new FakeCommand {
                    Int32Value = random.Next(), StringValue = fixture.Create <string>()
                },
                new FakeCommand {
                    Int32Value = random.Next(), StringValue = fixture.Create <string>()
                },
            }
                select new Envelope(Guid.NewGuid(), command, null, Guid.NewGuid(), null));

            using (var db = new ProcessManagerDbContext(_dbContextOptions))
            {
                db.PendingCommands.AddRange(from envelope in envelopes
                                            select PendingCommand.FromEnvelope(processManager, envelope, serializer));

                db.PendingCommands.AddRange(from envelope in new[]
                {
                    new Envelope(new object()),
                    new Envelope(new object()),
                    new Envelope(new object()),
                }
                                            select PendingCommand.FromEnvelope(noiseProcessManager, envelope, serializer));

                await db.SaveChangesAsync();
            }

            var messageBus = new MessageBus();

            var sut = new SqlCommandPublisher(
                () => new ProcessManagerDbContext(_dbContextOptions),
                serializer,
                messageBus,
                Mock.Of <IScheduledMessageBus>());

            // Act
            await sut.FlushCommands(processManager.Id, CancellationToken.None);

            // Assert
            messageBus.Sent.Should().BeEquivalentTo(envelopes, opts => opts.WithStrictOrdering().RespectingRuntimeTypes());
        }
        public async Task given_message_bus_fails_FlushCommands_deletes_no_command()
        {
            // Arrange
            var serializer     = new JsonMessageSerializer();
            var processManager = new FakeProcessManager();
            var random         = new Random();
            var commands       = new List <PendingCommand>(
                from command in new[]
            {
                new FakeCommand {
                    Int32Value = random.Next(), StringValue = Guid.NewGuid().ToString()
                },
                new FakeCommand {
                    Int32Value = random.Next(), StringValue = Guid.NewGuid().ToString()
                },
                new FakeCommand {
                    Int32Value = random.Next(), StringValue = Guid.NewGuid().ToString()
                },
            }
                let envelope = new Envelope(command)
                               select PendingCommand.FromEnvelope(processManager, envelope, serializer));

            using (var db = new ProcessManagerDbContext(_dbContextOptions))
            {
                db.PendingCommands.AddRange(commands);
                await db.SaveChangesAsync();
            }

            IMessageBus messageBus = Mock.Of <IMessageBus>();
            var         exception  = new InvalidOperationException();

            Mock.Get(messageBus)
            .Setup(x => x.Send(It.IsAny <IEnumerable <Envelope> >(), It.IsAny <CancellationToken>()))
            .ThrowsAsync(exception);

            var sut = new SqlCommandPublisher(
                () => new ProcessManagerDbContext(_dbContextOptions),
                serializer,
                messageBus,
                Mock.Of <IScheduledMessageBus>());

            // Act
            Func <Task> action = () => sut.FlushCommands(processManager.Id, CancellationToken.None);

            // Assert
            action.Should().Throw <InvalidOperationException>().Which.Should().BeSameAs(exception);
            using (var db = new ProcessManagerDbContext(_dbContextOptions))
            {
                IQueryable <PendingCommand> query = from c in db.PendingCommands
                                                    where c.ProcessManagerId == processManager.Id
                                                    select c;
                List <PendingCommand> actual = await query.ToListAsync();

                actual.Should().BeEquivalentTo(commands, opts => opts.RespectingRuntimeTypes());
            }
        }
Example #5
0
        public void FromEnvelope_sets_CorrelationId_correctly()
        {
            var fixture        = new Fixture();
            var envelope       = new Envelope(Guid.NewGuid(), fixture.Create <FooCommand>(), correlationId: Guid.NewGuid());
            var processManager = new FooProcessManager();
            var serializer     = new JsonMessageSerializer();

            var actual = PendingCommand.FromEnvelope(processManager, envelope, serializer);

            actual.CorrelationId.Should().Be(envelope.CorrelationId);
        }
Example #6
0
        public void FromEnvelope_sets_ProcessManagerId_correctly()
        {
            var fixture        = new Fixture();
            var envelope       = new Envelope(fixture.Create <FooCommand>());
            var processManager = new FooProcessManager();
            var serializer     = new JsonMessageSerializer();

            var actual = PendingCommand.FromEnvelope(processManager, envelope, serializer);

            TestContext.WriteLine($"{actual.ProcessManagerId}");
            actual.ProcessManagerId.Should().Be(processManager.Id);
        }
        public async Task FlushCommands_absorbs_exception_caused_by_that_some_pending_command_already_deleted_since_loaded()
        {
            // Arrange
            var messageBus = new CompletableMessageBus();
            var serializer = new JsonMessageSerializer();
            var sut        = new SqlCommandPublisher(
                () => new ProcessManagerDbContext(_dbContextOptions),
                serializer,
                messageBus,
                Mock.Of <IScheduledMessageBus>());

            var processManager = new FakeProcessManager();

            using (var db = new ProcessManagerDbContext(_dbContextOptions))
            {
                db.PendingCommands.AddRange(
                    new[]
                {
                    new FakeCommand(),
                    new FakeCommand(),
                    new FakeCommand(),
                }
                    .Select(c => new Envelope(c))
                    .Select(e => PendingCommand.FromEnvelope(processManager, e, serializer)));
                await db.SaveChangesAsync();
            }

            // Act
            Func <Task> action = async() =>
            {
                Task flushTask = sut.FlushCommands(processManager.Id, CancellationToken.None);
                using (var db = new ProcessManagerDbContext(_dbContextOptions))
                {
                    List <PendingCommand> pendingCommands = await db
                                                            .PendingCommands
                                                            .Where(c => c.ProcessManagerId == processManager.Id)
                                                            .OrderByDescending(c => c.Id)
                                                            .Take(1)
                                                            .ToListAsync();

                    db.PendingCommands.RemoveRange(pendingCommands);
                    await db.SaveChangesAsync();
                }

                messageBus.Complete();
                await flushTask;
            };

            // Assert
            action.Should().NotThrow();
        }
Example #8
0
        public void FromEnvelope_sets_CommandJson_correctly()
        {
            var        fixture        = new Fixture();
            FooCommand command        = fixture.Create <FooCommand>();
            var        envelope       = new Envelope(command);
            var        processManager = new FooProcessManager();
            var        serializer     = new JsonMessageSerializer();

            var actual = PendingCommand.FromEnvelope(processManager, envelope, serializer);

            serializer.Deserialize(actual.CommandJson)
            .Should().BeOfType <FooCommand>()
            .Subject.ShouldBeEquivalentTo(command);
        }
 private static async Task RemoveCommand(
     ProcessManagerDbContext dbContext,
     PendingCommand command,
     CancellationToken cancellationToken)
 {
     try
     {
         dbContext.PendingCommands.Remove(command);
         await dbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
     }
     catch (DbUpdateConcurrencyException)
     {
         dbContext.Entry(command).State = EntityState.Detached;
     }
 }
        public async Task FlushCommands_deletes_all_commands_associated_with_specified_process_manager()
        {
            // Arrange
            var serializer = new JsonMessageSerializer();

            var processManager      = new FakeProcessManager();
            var noiseProcessManager = new FakeProcessManager();

            const int noiseCommandCount = 3;

            using (var db = new ProcessManagerDbContext(_dbContextOptions))
            {
                var commands = new List <PendingCommand>(
                    from command in Enumerable.Repeat(new FakeCommand(), 3)
                    let envelope = new Envelope(command)
                                   select PendingCommand.FromEnvelope(processManager, envelope, serializer));

                commands.AddRange(
                    from command in Enumerable.Repeat(new FakeCommand(), noiseCommandCount)
                    let envelope = new Envelope(command)
                                   select PendingCommand.FromEnvelope(noiseProcessManager, envelope, serializer));

                var random = new Random();
                db.PendingCommands.AddRange(
                    from command in commands
                    orderby random.Next()
                    select command);

                await db.SaveChangesAsync();
            }

            var sut = new SqlCommandPublisher(
                () => new ProcessManagerDbContext(_dbContextOptions),
                serializer,
                Mock.Of <IMessageBus>(),
                Mock.Of <IScheduledMessageBus>());

            // Act
            await sut.FlushCommands(processManager.Id, CancellationToken.None);

            // Assert
            using (var db = new ProcessManagerDbContext(_dbContextOptions))
            {
                (await db.PendingCommands.AnyAsync(c => c.ProcessManagerId == processManager.Id)).Should().BeFalse();
                (await db.PendingCommands.CountAsync(c => c.ProcessManagerId == noiseProcessManager.Id)).Should().Be(noiseCommandCount);
            }
        }
        public async Task EnqueueAll_publishes_all_pending_commands_asynchronously()
        {
            // Arrange
            var serializer = new JsonMessageSerializer();

            var fixture = new Fixture();

            using (var db = new FooProcessManagerDbContext())
            {
                for (int i = 0; i < 3; i++)
                {
                    var processManager = new FooProcessManager();
                    db.PendingCommands.AddRange(from command in Enumerable.Repeat(new FooCommand(), 3)
                                                let envelope = new Envelope(command)
                                                               select PendingCommand.FromEnvelope(processManager, envelope, serializer));
                }

                await db.SaveChangesAsync();
            }

            var sut = new SqlCommandPublisher(
                () => new FooProcessManagerDbContext(),
                serializer,
                Mock.Of <IMessageBus>(),
                Mock.Of <IScheduledMessageBus>());

            // Act
            sut.EnqueueAll(CancellationToken.None);

            // Assert
            using (var db = new FooProcessManagerDbContext())
            {
                int maximumRetryCount = 5;
                var retryPolicy       = new RetryPolicy <bool>(
                    maximumRetryCount,
                    new DelegatingTransientFaultDetectionStrategy <bool>(any => any == true),
                    new ConstantRetryIntervalStrategy(TimeSpan.FromSeconds(1.0)));
                (await retryPolicy.Run(db.PendingCommands.AnyAsync, CancellationToken.None)).Should().BeFalse();
            }
        }
Example #12
0
        public void FromEnvelope_generates_PendingCommand_correctly()
        {
            // Arrange
            var processManager = new FakeProcessManager();
            var messageId      = Guid.NewGuid();
            var correlationId  = Guid.NewGuid();
            var message        = new FakeCommand
            {
                Int32Value  = new Random().Next(),
                StringValue = Guid.NewGuid().ToString(),
            };
            var envelope   = new Envelope(messageId, message, correlationId: correlationId);
            var serializer = new JsonMessageSerializer();

            // Act
            var actual = PendingCommand.FromEnvelope(processManager, envelope, serializer);

            // Assert
            actual.ProcessManagerType.Should().Be(typeof(FakeProcessManager).FullName);
            actual.ProcessManagerId.Should().Be(processManager.Id);
            actual.MessageId.Should().Be(messageId);
            actual.CorrelationId.Should().Be(correlationId);
            actual.CommandJson.Should().Be(serializer.Serialize(message));
        }