private Envelope RestoreEnvelope(PendingCommand command) => new Envelope( command.MessageId, _serializer.Deserialize(command.CommandJson), operationId: command.OperationId, correlationId: command.CorrelationId, contributor: command.Contributor);
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()); } }
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); }
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(); }
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(); } }
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)); }