public async Task Should_insert_new_state_instance_on_submitted() { var orderStateMachine = new OrderStateMachine(); var harness = new InMemoryTestHarness { TestTimeout = TimeSpan.FromSeconds(5) }; var saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(orderStateMachine); await harness.Start(); try { var orderId = NewId.NextGuid(); await harness.Bus.Publish <IOrderSubmitted>(new { OrderId = orderId, ExternalOrderId = "00000001" }); Assert.That(saga.Created.Select(x => x.CorrelationId == orderId).Any(), Is.True); var instanceId = await saga.Exists(orderId, x => x.Submitted); Assert.That(instanceId, Is.Not.Null); var instance = saga.Sagas.Contains(instanceId.Value); Assert.That(instance.ExternalOrderId, Is.EqualTo("00000001")); } finally { await harness.Stop(); } }
public async Task Should_create_a_state_instance() { var orderStateMachine = new OrderStateMachine(); var harness = new InMemoryTestHarness { TestTimeout = TimeSpan.FromSeconds(5) }; var saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(new OrderStateMachine()); await harness.Start(); try { var orderId = NewId.NextGuid(); await harness.Bus.Publish <OrderSubmitted>(new { OrderId = orderId, InVar.Timestamp, CustomerNumber = "123456" }); var instance = saga.Created.Contains(orderId); await saga.Exists(orderId, x => x.Submitted); //race condtion wait for state change Assert.True(saga.Created.Select(x => x.CorrelationId == orderId).Any()); Assert.NotNull(instance); Assert.Equal(orderStateMachine.Submitted.Name, instance.CurrentState); } finally { await harness.Stop(); } }
public async Task Should_create_a_state_instance() { var orderStateMachine = new OrderStateMachine(); var harness = new InMemoryTestHarness(); var saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(orderStateMachine); await harness.Start(); try { var orderId = NewId.NextGuid(); await harness.Bus.Publish <IOrderSubmitted>(new { OrderId = orderId, InVar.Timestamp, CustomerNumber = "12345" }); Assert.That(saga.Created.Select(x => x.CorrelationId == orderId).Any(), Is.True); var instanceId = await saga.Exists(orderId, x => x.Submitted); Assert.That(instanceId, Is.Not.Null); var instance = saga.Sagas.Contains(instanceId.Value); Assert.That(instance.CustomerNumber, Is.EqualTo("12345")); } finally { await harness.Stop(); } }
public async Task Should_respond_to_status_checks() { var harness = new InMemoryTestHarness(); var orderStateMachine = new OrderStateMachine(); var saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(orderStateMachine); await harness.Start(); try { var orderId = NewId.NextGuid(); await harness.Bus.Publish <OrderSubmitted>(new { OrderId = orderId, InVar.Timestamp, CustomerNumber = customerNumber }); Assert.That(saga.Created.Select(x => x.CorrelationId == orderId).Any(), Is.True); var instanceId = await saga.Exists(orderId, x => x.Submitted); Assert.That(instanceId, Is.Not.Null); var requestClient = await harness.ConnectRequestClient <CheckOrder>(); var response = await requestClient.GetResponse <OrderStatus>(new { OrderId = orderId }); Assert.That(response.Message.State, Is.EqualTo(orderStateMachine.Submitted.Name)); } finally { await harness.Stop(); } }
private OrderStateMachine CreateStateMachine() { var stateMachine = OrderStateMachine.CreateInitializable(); stateMachine.GuardClauseFromDealingToValidatingUsingTriggerAddTrade = () => IsFilled(_workingData); stateMachine.GuardClauseFromWorkingToValidatingUsingTriggerAddTrade = () => IsFilled(_workingData); stateMachine.GuardClauseFromUndefinedToAcceptingUsingTriggerSendRequest = () => IsFilled(_workingData); return(stateMachine); }
public async Task SetUp() { _harness = new InMemoryTestHarness { TestTimeout = TimeSpan.FromSeconds(5) }; _orderStateMachine = new OrderStateMachine(); _saga = _harness.StateMachineSaga <OrderState, OrderStateMachine>(_orderStateMachine); await _harness.Start(); }
public void I_want_to_see_you_pretty() { var machine = new OrderStateMachine(); var generator = new StateMachineGraphGenerator(); string filename = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "graph.png"); generator.SaveGraphToFile(machine.GetGraphData(), 2560, 1920, filename); }
public void Show_me_the_state_machine() { var orderStateMachine = new OrderStateMachine(); var graph = orderStateMachine.GetGraph(); var generator = new StateMachineGraphvizGenerator(graph); string dots = generator.CreateDotFile(); Console.WriteLine(dots); Debug.WriteLine(dots); }
public void I_want_to_see_you_pretty() { var machine = new OrderStateMachine(); var generator = new StateMachineGraphGenerator(); string filename = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "graph.png"); generator.SaveGraphToFile(machine.GetGraphData(), 2560, 1920, filename); }
public void Show_me_the_StateMachine() { // 주어진 상태기계를 GraphViz 로 시각화가 가능. var orderStateMachine = new OrderStateMachine(); var graph = orderStateMachine.GetGraph(); var generator = new StateMachineGraphvizGenerator(graph); var dots = generator.CreateDotFile(); Console.WriteLine(dots); }
public Task <bool> UpdateOrder(Pizza pizza) { var old = _order.Pizza.SingleOrDefault(x => x.Id == pizza.Id); if (old != null) { old.Status = pizza.Status; } if (old != null) { _logger.LogInformation($"Order has been updated new status {old.Status}"); } var orderStateMachine = new OrderStateMachine(_order); if (orderStateMachine.CanFire(Trigger.UpdateOrder) && _order.Status <= Status.ReadyForDelivery) { orderStateMachine.Fire(Trigger.UpdateOrder); UpdateOrderForAPI(_order); } if (_order.Status == Status.Delivering) { if (orderStateMachine.CanFire(Trigger.UpdateOrder)) { orderStateMachine.Fire(Trigger.UpdateOrder); if (_order.Status != Status.Delivered) { UpdateOrderForAPI(_order); } else { UpdateOrderForAPI(_order, false); } } if (_order.Status == Status.Delivered) { UpdateOrderForAPI(_order); _logger.LogInformation($"Order Was delivered"); //try //{ // base.ClearStateAsync(); //} //catch (Exception e) //{ // _logger.LogError($"Exception clearing the grain storage: {e}"); //} } } _logger.LogInformation($"Order status {_order.Status}"); return(Task.FromResult(true)); }
Task <string> IHello.SayHello(string greeting) { var order = new Order { Status = Status.Started }; var orderStateMachine = new OrderStateMachine(order); orderStateMachine.Fire(Trigger.UpdateOrder); _logger.LogInformation($"SayHello message received: greeting = '{greeting}'"); return(Task.FromResult($"You said: '{greeting}', I say: Hello! {order.Status}")); }
public async Task Should_update_info_when_submitted_after_any_other_state() { var harness = new InMemoryTestHarness { TestTimeout = TimeSpan.FromSeconds(3) }; var orderStateMachine = new OrderStateMachine(); var saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(orderStateMachine); await harness.Start(); try { var orderId = Guid.NewGuid(); await harness.Bus.Publish <OrderSubmittedEvent>(new { OrderId = orderId }); var instance = await saga.Exists(orderId, x => x.Submitted); instance.Should().NotBeNull(); await harness.Bus.Publish <OrderAcceptedEvent>(new { OrderId = orderId, InVar.Timestamp, }); instance = await saga.Exists(orderId, x => x.Accepted); instance.Should().NotBeNull(); var timestamp = new DateTime(2020, 01, 01); await harness.Bus.Publish <OrderSubmittedEvent>(new { OrderId = orderId, CustomerNumber = "0987", Timestamp = timestamp }); instance = await saga.Exists(orderId, x => x.Accepted); instance.Should().NotBeNull(); var data = saga.Sagas.Contains(orderId); data.SubmitDate.Should().Be(timestamp); data.CustomerNumber.Should().Be("0987"); } finally { await harness.Stop(); } }
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices((hostContext, services) => { var hostConfig = hostContext.Configuration; services.AddLogging(); services.ConfigureTelemetryModule <DependencyTrackingTelemetryModule>((module, _) => module.IncludeDiagnosticSourceActivities.Add("MassTransit")); services.AddApplicationInsightsTelemetryWorkerService(); services.AddMassTransit(x => { x.AddConsumersFromNamespaceContaining <SubmitOrderConsumer>(); x.AddBus(context => Bus.Factory.CreateUsingRabbitMq( configurator => { var uri = new Uri(hostConfig["RabbitMQ"]); var usernameAndPassword = uri.UserInfo.Split(":"); configurator.Host(uri, h => { h.Username(WebUtility.UrlDecode(usernameAndPassword[0])); h.Password(WebUtility.UrlDecode(usernameAndPassword[1])); }); configurator.ReceiveEndpoint("submit-order", e => { e.Consumer <SubmitOrderConsumer>(); }); configurator.ReceiveEndpoint("order-observer", e => { e.Consumer <OrderSubmittedConsumer>(); }); configurator.ReceiveEndpoint("order-state", e => { var machine = new OrderStateMachine(); var repository = new InMemorySagaRepository <OrderState>(); e.StateMachineSaga(machine, repository); EndpointConvention.Map <OrderProcessed>(e.InputAddress); }); configurator.ReceiveEndpoint("execute-process-order", e => { e.ExecuteActivityHost <ProcessOrderActivity, ProcessOrderArguments>(); EndpointConvention.Map <ProcessOrderArguments>(e.InputAddress); }); })); }); services.AddHostedService <Worker>(); });
public async Task Should_create_a_state_instance() { var harness = new InMemoryTestHarness() { TestTimeout = TimeSpan.FromSeconds(1) }; var orderStateMachine = new OrderStateMachine(); var saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(orderStateMachine); await harness.Start(); var orderId = NewId.NextGuid(); var customerNumber = "1234"; try { // 아래는 "없는 걸" 테스트 하므로, Timeout 문제 발생함. 따라서 test harness에 timeout 을 주었다. Assert.That(saga.Created.Select(x => x.CorrelationId == orderId).Any(), Is.False); await harness.Bus.Publish <OrderSubmitted>(new { OrderId = orderId, Timestamp = InVar.Timestamp, CustomerNumber = customerNumber }); Assert.That(saga.Created.Select(x => x.CorrelationId == orderId).Any(), Is.True); // 비동기 코드에 대한 테스트는 항상 Race Condition이 있을 수 있다. // 으래 코드는 `Task.Delay()` 가 없으면 실패한다. (테스트 코드가 실행되는 속도가 메시지 처리되는 속도 보다 빠르기 때문) // await Task.Delay(TimeSpan.FromSeconds(1)); // var instance = saga.Created.Contains(orderId); // Assert.That(instance, Is.Not.Null); // Assert.That(instance.CurrentState, Is.EqualTo(orderStateMachine.Submitted.Name)); // 따라서, Masstransit Test Harness Saga 는 "특정 saga 가 특정 상태가 되기를 대기 하게 할 수 있다. // orderId 의 correlation id 를 가지는 saga 가 submitted 상태에 있을 때 가지 대기 var instanceId = await saga.Exists(orderId, x => x.Submitted, timeout : null); // timeout 을 null 로 주면, Test harness의 TestTimeout 값이 사용됨. Assert.That(instanceId, Is.Not.Null); var instance = saga.Sagas.Contains(instanceId.Value); Assert.That(instance.CustomerNumber, Is.EqualTo(customerNumber)); } finally { await harness.Stop(); } }
public async Task Should_be_cancelled_when_CustomerAccountClosed() { var harness = new InMemoryTestHarness() { TestTimeout = TimeSpan.FromSeconds(1) }; var orderStateMachine = new OrderStateMachine(); var saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(orderStateMachine); await harness.Start(); var orderId = NewId.NextGuid(); var customerNumber = "1234"; try { // 아래는 "없는 걸" 테스트 하므로, Timeout 문제 발생함. 따라서 test harness에 timeout 을 주었다. Assert.That(saga.Created.Select(x => x.CorrelationId == orderId).Any(), Is.False); await harness.Bus.Publish <OrderSubmitted>(new { OrderId = orderId, Timestamp = InVar.Timestamp, CustomerNumber = customerNumber }); Assert.That(saga.Created.Select(x => x.CorrelationId == orderId).Any(), Is.True); var instanceId = await saga.Exists(orderId, x => x.Submitted); Assert.That(instanceId, Is.Not.Null); await harness.Bus.Publish <CustomerAccountClosed>(new { //CustomerId = NewId.NextGuid(), // 상관없는 필드. Timestamp = InVar.Timestamp, CustomerNumber = customerNumber, }); instanceId = await saga.Exists(orderId, x => x.Cancelled); Assert.That(instanceId, Is.Not.Null); } finally { await harness.Stop(); } }
public async Task Should_respond_to_status_check_requested_event() { var harness = new InMemoryTestHarness { TestTimeout = TimeSpan.FromSeconds(3) }; var orderStateMachine = new OrderStateMachine(); var orderSaga = harness.StateMachineSaga <OrderState, OrderStateMachine>(orderStateMachine); await harness.Start(); try { var orderId = NewId.NextGuid(); await harness.Bus.Publish <OrderSubmittedEvent>(new { OrderId = orderId, InVar.Timestamp, CustomerNumber = "1234" }); orderSaga.Created .Select(s => s.CorrelationId == orderId) .Any() .Should().BeTrue(); var instanceId = await orderSaga.Exists(orderId, s => s.Submitted); instanceId.Should().NotBeNull(); var requestClient = await harness.ConnectRequestClient <CheckOrderRequestedEvent>(); var response = await requestClient.GetResponse <OrderStatusResponse>(new { OrderId = orderId }); orderSaga.Consumed.Select <CheckOrderRequestedEvent>().Any().Should().BeTrue(); response.Message.State.Should().Be(orderStateMachine.Submitted.Name); } finally { await harness.Stop(); } }
public async Task Should_cancel_order_when_account_closed() { var orderStateMachine = new OrderStateMachine(); var harness = new InMemoryTestHarness { TestTimeout = TimeSpan.FromSeconds(2) }; var saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(orderStateMachine); await harness.Start(); try { var orderId = NewId.NextGuid(); const string customerNumber = "12345"; await harness.Bus.Publish <OrderSubmittedEvent>(new { OrderId = orderId, InVar.Timestamp, CustomerNumber = customerNumber }); saga.Created.Select(x => x.CorrelationId == orderId).Any().Should().BeTrue(); var instanceId = await saga.Exists(orderId, x => x.Submitted); instanceId.Should().NotBeNull(); await harness.Bus.Publish <CustomerAccountClosedEvent>(new { CustomerId = InVar.Id, CustomerNumber = customerNumber }); instanceId = await saga.Exists(orderId, x => x.Cancelled); instanceId.Should().NotBeNull(); } finally { await harness.Stop(); } }
public async Task <Order> SetOrderStatusAsync(int orderId, OrderStatus newOrderStatus) { var order = new Order(); using (var transaction = _orderDbContext.Database.BeginTransaction()) { try { order = await GetOrderByIdAsync(orderId); if (!OrderStateMachine.IsTransitionAllowed(order.Status.StatusId, newOrderStatus)) { throw new InvalidOperationException("Transition is not allowed by state machine."); } order.StatusId = newOrderStatus; if (newOrderStatus == OrderStatus.Failed || newOrderStatus == OrderStatus.Cancelled) { foreach (var orderItem in order.OrderItems) { var warehouseItem = await _orderDbContext.WarehouseItems .FirstOrDefaultAsync(wi => wi.Item == orderItem.Item); warehouseItem.Amount += orderItem.Amount; } } if (!await SaveChangesAsync()) { throw new DbUpdateException("Database failure"); } transaction.Commit(); } catch (Exception e) { transaction.Rollback(); throw e; } } return(order); }
public async Task Should_accept_when_order_is_accepted() { var orderStateMachine = new OrderStateMachine(); var harness = new InMemoryTestHarness(); var saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(orderStateMachine); EndpointConvention.Map <MyTestCommand>(new Uri("loopback://localhost/my-test-command")); await harness.Start(); try { var orderId = NewId.NextGuid(); await harness.Bus.Publish <OrderSubmitted>(new { OrderId = orderId, InVar.Timestamp, CustomerNumber = "12345" }); Assert.That(saga.Created.Select(x => x.CorrelationId == orderId).Any(), Is.True); var instanceId = await saga.Exists(orderId, x => x.Submitted); Assert.That(instanceId, Is.Not.Null); await harness.Bus.Publish <OrderAccepted>(new { OrderId = orderId, InVar.Timestamp, }); instanceId = await saga.Exists(orderId, x => x.Accepted); Assert.That(instanceId, Is.Not.Null); } finally { await harness.Stop(); } }
public async Task Should_respond_to_status_check() { var harness = new InMemoryTestHarness() { TestTimeout = TimeSpan.FromSeconds(1) }; var orderStateMachine = new OrderStateMachine(); var saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(orderStateMachine); await harness.Start(); var orderId = NewId.NextGuid(); var customerNumber = "1234"; try { // 아래는 "없는 걸" 테스트 하므로, Timeout 문제 발생함. 따라서 test harness에 timeout 을 주었다. Assert.That(saga.Created.Select(x => x.CorrelationId == orderId).Any(), Is.False); await harness.Bus.Publish <OrderSubmitted>(new { OrderId = orderId, Timestamp = InVar.Timestamp, CustomerNumber = customerNumber }); Assert.That(saga.Created.Select(x => x.CorrelationId == orderId).Any(), Is.True); var requestClient = await harness.ConnectRequestClient <CheckOrder>(); var response = await requestClient.GetResponse <OrderStatus>(new { OrderId = orderId }); Assert.That(response.Message.State, Is.EqualTo(orderStateMachine.Submitted.Name)); } finally { await harness.Stop(); } }
private void SaleReturnOrderTransitionFromInitState(OrderStateMachine stateMachine, State <OrderCarrier> returnConfirmed) { //build SRO state transitions. //From Init to ReturnConfirmed. stateMachine.AddStateTransition(new State <OrderCarrier>((short)OrderState.Init, OrderState.Init.ToString()), returnConfirmed, (orderCarrier, startState, endState, token) => { //Conditions for SRO from init to ReturnConfirmed. //Precodition: //+RMA in Completed state and it should be Approved //+Order is of type SalesReturnOrder if (orderCarrier.Type != OrderType.SalesReturnOrder || orderCarrier.RmaSystemId is null || orderCarrier.RmaSystemId == Guid.Empty) { return(false); } var rma = _rmaService.Get(orderCarrier.RmaSystemId.Value); //RmaState.Completed denote that the Rma process is completed, the ApprovateCode.Approved denote that it actually is approved. return(rma?.State == RmaState.Completed && rma?.ApprovalCode == ApprovalCode.Approved); },
public async Task SubmitOrderConsumer_Accepted() { var orderStateMachine = new OrderStateMachine(); var harness = new InMemoryTestHarness(); var saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(orderStateMachine); try { await harness.Start(); var orderId = NewId.NextGuid(); await harness.Bus.Publish <IOrderAcceptedEvent>(new { OrderId = orderId, CreationDateTime = InVar.Timestamp, Amount = 900 }); saga.Created.Select(x => x.CorrelationId == orderId).Any().Should().Be.True(); var correlationId = await saga.Exists(orderId, x => x.Created); correlationId.HasValue.Should().Be.True(); var instance = saga.Sagas.Contains(correlationId.Value); instance.CurrentState.Should().Be.EqualTo("Created"); instance.CorrelationId.Should().Be.EqualTo(orderId); instance.Amount.Should().Be.EqualTo(900); harness.Sent.Select <IRequestValidateOrder>().Any().Should().Be.True(); harness.Published.Select <IRequestValidateOrder>().Any().Should().Be.False(); } finally { await harness.Stop(); } }
public async Task Should_cancel_when_customer_account_closed() { var orderStateMachine = new OrderStateMachine(); var harness = new InMemoryTestHarness(); var saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(orderStateMachine); await harness.Start(); try { var orderId = NewId.NextGuid(); await harness.Bus.Publish <IOrderSubmitted>(new { OrderId = orderId, InVar.Timestamp, CustomerNumber = "12345" }); Assert.That(saga.Created.Select(x => x.CorrelationId == orderId).Any(), Is.True); var instanceId = await saga.Exists(orderId, x => x.Submitted); Assert.That(instanceId, Is.Not.Null); await harness.Bus.Publish <ICustomerAccountClosed>(new { CustomerId = InVar.Id, CustomerNumber = "12345" }); instanceId = await saga.Exists(orderId, x => x.Canceled); Assert.That(instanceId, Is.Not.Null); } finally { await harness.Stop(); } }
public async Task Should_cancel_when_customer_account_closed() { var orderStateMachine = new OrderStateMachine(); var harness = new InMemoryTestHarness { TestTimeout = TimeSpan.FromSeconds(5) }; var saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(new OrderStateMachine()); await harness.Start(); try { var orderId = NewId.NextGuid(); await harness.Bus.Publish <OrderSubmitted>(new { OrderId = orderId, InVar.Timestamp, CustomerNumber = "123456" }); var instance = saga.Created.Contains(orderId); var instanceId = await saga.Exists(orderId, x => x.Submitted); //race condition wait for state change Assert.NotNull(instanceId); await harness.Bus.Publish <CustomerAccountClosed>(new { CustomerId = InVar.Id, CustomerNumber = "123456" }); instanceId = await saga.Exists(orderId, x => x.Canceled); Assert.NotNull(instanceId); } finally { await harness.Stop(); } }
public async Task Should_create_a_state_instance() { var harness = new InMemoryTestHarness { TestTimeout = TimeSpan.FromSeconds(3) }; var orderStateMachine = new OrderStateMachine(); var orderSaga = harness.StateMachineSaga <OrderState, OrderStateMachine>(orderStateMachine); await harness.Start(); try { var orderId = NewId.NextGuid(); await harness.Bus.Publish <OrderSubmittedEvent>(new { OrderId = orderId, InVar.Timestamp, CustomerNumber = "1234" }); orderSaga.Created .Select(s => s.CorrelationId == orderId) .Any() .Should().BeTrue(); var instanceId = await orderSaga.Exists(orderId, s => s.Submitted); instanceId.Should().NotBeNull(); var instance = orderSaga.Sagas.Contains(orderId); instance.CustomerNumber.Should().Be("1234"); } finally { await harness.Stop(); } }
public async Task Should_respond_to_status_checks() { var harness = new InMemoryTestHarness(); var orderStateMachine = new OrderStateMachine(); StateMachineSagaTestHarness <OrderState, OrderStateMachine> saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(orderStateMachine); await harness.Start(); try { Guid orderId = NewId.NextGuid(); await harness.Bus.Publish <OrderSubmitted>(new { OrderId = orderId, InVar.Timestamp, CustomerNumber = "12345" }); Guid?instanceId = await saga.Exists(orderId, x => x.Submitted); instanceId.Should().Be(orderId); var requestClient = await harness.ConnectRequestClient <CheckOrder>(); var response = await requestClient.GetResponse <OrderStatus>(new { OrderId = orderId }); response.Message.State.Should().Be(orderStateMachine.Submitted.Name); } finally { await harness.Stop(); } }
public async Task Should_respond_to_status_checks() { var orderStateMachine = new OrderStateMachine(); var harness = new InMemoryTestHarness { TestTimeout = TimeSpan.FromSeconds(5) }; var saga = harness.StateMachineSaga <OrderState, OrderStateMachine>(new OrderStateMachine()); await harness.Start(); try { var orderId = NewId.NextGuid(); await harness.Bus.Publish <OrderSubmitted>(new { OrderId = orderId, InVar.Timestamp, CustomerNumber = "123456" }); var instance = saga.Created.Contains(orderId); await saga.Exists(orderId, x => x.Submitted); //race condtion wait for state change var requestClient = await harness.ConnectRequestClient <CheckOrder>(); var response = await requestClient.GetResponse <OrderStatus>(new { OrderId = orderId }); Assert.Equal(orderStateMachine.Submitted.Name, response.Message.State); } finally { await harness.Stop(); } }
static async Task Main(string[] args) { var saga = new OrderStateMachine(); var repo = new InMemorySagaRepository <OrderStateData>(); var builder = new HostBuilder() .ConfigureServices((hostContext, services) => { services.TryAddSingleton(KebabCaseEndpointNameFormatter.Instance); services.AddMassTransit(cfg => { cfg.AddBus(provider => RabbitMqBus.ConfigureBus(provider, (cfg, host) => { cfg.ReceiveEndpoint(BusConstants.SagaBusQueue, e => { e.StateMachineSaga(saga, repo); }); })); }); services.AddMassTransitHostedService(); }); await builder.RunConsoleAsync(); }
public Order() { EventLogs = new List <OrderEventLog>(); _stateMachine = OrderStateMachine.CreateInitializable(); }
public bool Start(HostControl hostControl) { var saga = new OrderStateMachine(); var repo = new InMemorySagaRepository <Order>(); _busObserver = new BusObserver(); _busControl = BusConfigurator.ConfigureBus((cfg, host) => { cfg.AddBusFactorySpecification(new BusObserverSpecification(() => _busObserver)); cfg.ReceiveEndpoint(host, RabbitMqConstants.SagaQueue, e => { cfg.UseNLog(new LogFactory()); cfg.EnablePerformanceCounters(); e.UseRetry(Retry.Interval(5, TimeSpan.FromSeconds(5))); e.UseCircuitBreaker(cb => { cb.TripThreshold = 15; cb.ResetInterval(TimeSpan.FromMinutes(5)); cb.TrackingPeriod = TimeSpan.FromMinutes(1); cb.ActiveThreshold = 10; }); //e.UseRetry(Retry.Except(typeof(ArgumentException), // typeof(NotAcceptedStateMachineException)).Interval(10, TimeSpan.FromSeconds(5))); //TODO: Create a custom filter policy for inner exceptions on Sagas: http://stackoverflow.com/questions/37041293/how-to-use-masstransits-retry-policy-with-sagas e.StateMachineSaga(saga, repo); }); }); var consumeObserver = new LogConsumeObserver(); _busControl.ConnectConsumeObserver(consumeObserver); //TODO: See how to do versioning of messages (best practices) //http://masstransit.readthedocs.io/en/master/overview/versioning.html try { _busHandle = _busControl.Start(); Console.WriteLine("Saga active.. Press enter to exit"); GlobalConfiguration.Configuration.UseMongoStorage("mongodb://localhost:27017", "hangfire-masstransit"); hangfireServer = new BackgroundJobServer(); Console.WriteLine("Hangfire Server started. Press any key to exit..."); WebApp.Start <Startup>("http://localhost:1235"); } catch { hangfireServer.Dispose(); _busControl.Stop(); throw; } return(true); }