コード例 #1
0
        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();
            }
        }
コード例 #2
0
        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();
            }
        }
コード例 #3
0
        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();
            }
        }
コード例 #4
0
        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();
            }
        }
コード例 #5
0
ファイル: Order.cs プロジェクト: Tramber/YOMS
        private OrderStateMachine CreateStateMachine()
        {
            var stateMachine = OrderStateMachine.CreateInitializable();

            stateMachine.GuardClauseFromDealingToValidatingUsingTriggerAddTrade     = () => IsFilled(_workingData);
            stateMachine.GuardClauseFromWorkingToValidatingUsingTriggerAddTrade     = () => IsFilled(_workingData);
            stateMachine.GuardClauseFromUndefinedToAcceptingUsingTriggerSendRequest = () => IsFilled(_workingData);
            return(stateMachine);
        }
コード例 #6
0
 public async Task SetUp()
 {
     _harness = new InMemoryTestHarness {
         TestTimeout = TimeSpan.FromSeconds(5)
     };
     _orderStateMachine = new OrderStateMachine();
     _saga = _harness.StateMachineSaga <OrderState, OrderStateMachine>(_orderStateMachine);
     await _harness.Start();
 }
コード例 #7
0
        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);
        }
コード例 #8
0
        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);
        }
コード例 #9
0
		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);
        }
コード例 #11
0
        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));
        }
コード例 #12
0
        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}"));
        }
コード例 #13
0
        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();
            }
        }
コード例 #14
0
        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();
            }
        }
コード例 #17
0
        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();
            }
        }
コード例 #18
0
        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();
            }
        }
コード例 #19
0
        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);
        }
コード例 #20
0
        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();
            }
        }
コード例 #22
0
        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);
            },
コード例 #23
0
        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();
            }
        }
コード例 #24
0
        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();
            }
        }
コード例 #25
0
        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();
            }
        }
コード例 #26
0
        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();
            }
        }
コード例 #27
0
        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();
            }
        }
コード例 #28
0
        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();
            }
        }
コード例 #29
0
        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();
        }
コード例 #30
0
ファイル: Order.cs プロジェクト: Tramber/YOMS
 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);
        }