ebubekirdinc / SuuCat

SuuCat is a sample containerized application consisting of several microservices. Its purpose is to use microservice patterns in practice.
MIT License
103 stars 28 forks source link

Issue Starting MassTransit Saga Orchestration State Machine Container #7

Closed bkershaw closed 7 months ago

bkershaw commented 7 months ago

I encountered an issue while following the MassTransit getting started guide. After running the containers using the provided docker-compose file, I observed that all containers started successfully except for the MassTransit Saga Orchestration State Machine container. Upon inspecting the logs, I found that the state machine crashes on startup.

Error Log Details `Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object. at MassTransit.TransitionExtensions.TransitionTo[TSaga,TMessage](EventActivityBinder`2 source, State toState) in /_/src/MassTransit/SagaStateMachine/TransitionExtensions.cs:line 51 at SagaOrchestrationStateMachine.StateMachines.OrderStateMachine..ctor() in /Users/local/Projects/Demo/SuuCat/src/StateMachines/SagaOrchestrationStateMachine/StateMachines/OrderStateMachine.cs:line 44 at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor) at System.Reflection.ConstructorInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr) at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType) at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory) at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at MassTransit.Configuration.DependencyInjectionSagaStateMachineRegistrationExtensions.SagaRegistrar`2.<>c.b__0_0(IServiceProvider provider) in /_/src/MassTransit/DependencyInjection/Configuration/DependencyInjectionSagaStateMachineRegistrationExtensions.cs:line 84 at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType) at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory) at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at MassTransit.Configuration.RegistrationContext.GetService(Type serviceType) in /_/src/MassTransit/DependencyInjection/Configuration/RegistrationContext.cs:line 131 at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at MassTransit.DependencyInjection.Registration.SagaStateMachineRegistration`2.Configure(IReceiveEndpointConfigurator configurator, IRegistrationContext context) in /_/src/MassTransit/DependencyInjection/DependencyInjection/Registration/Sagas/SagaStateMachineRegistration.cs:line 44 at MassTransit.Configuration.RegistrationContext.ConfigureSaga(Type sagaType, IReceiveEndpointConfigurator configurator) in /_/src/MassTransit/DependencyInjection/Configuration/RegistrationContext.cs:line 55 at MassTransit.Configuration.BusRegistrationContext.<>c__DisplayClass7_1`1.b__0(T cfg) in /_/src/MassTransit/DependencyInjection/Configuration/BusRegistrationContext.cs:line 181 at MassTransit.RabbitMqTransport.Configuration.RabbitMqHostConfiguration.<>c__DisplayClass26_0.b__0(IRabbitMqReceiveEndpointConfigurator configurator) in /_/src/Transports/MassTransit.RabbitMqTransport/RabbitMqTransport/Configuration/RabbitMqHostConfiguration.cs:line 125 at MassTransit.RabbitMqTransport.Configuration.RabbitMqHostConfiguration.CreateReceiveEndpointConfiguration(RabbitMqReceiveSettings settings, IRabbitMqEndpointConfiguration endpointConfiguration, Action`1 configure) in /_/src/Transports/MassTransit.RabbitMqTransport/RabbitMqTransport/Configuration/RabbitMqHostConfiguration.cs:line 107 at MassTransit.RabbitMqTransport.Configuration.RabbitMqHostConfiguration.CreateReceiveEndpointConfiguration(String queueName, Action`1 configure) in /_/src/Transports/MassTransit.RabbitMqTransport/RabbitMqTransport/Configuration/RabbitMqHostConfiguration.cs:line 94 at MassTransit.RabbitMqTransport.Configuration.RabbitMqHostConfiguration.ReceiveEndpoint(String queueName, Action`1 configureEndpoint) in /_/src/Transports/MassTransit.RabbitMqTransport/RabbitMqTransport/Configuration/RabbitMqHostConfiguration.cs:line 130 at MassTransit.RabbitMqTransport.Configuration.RabbitMqHostConfiguration.ReceiveEndpoint(IEndpointDefinition definition, IEndpointNameFormatter endpointNameFormatter, Action`1 configureEndpoint) in /_/src/Transports/MassTransit.RabbitMqTransport/RabbitMqTransport/Configuration/RabbitMqHostConfiguration.cs:line 121 at MassTransit.RabbitMqTransport.Configuration.RabbitMqBusFactoryConfigurator.ReceiveEndpoint(IEndpointDefinition definition, IEndpointNameFormatter endpointNameFormatter, Action`1 configureEndpoint) in /_/src/Transports/MassTransit.RabbitMqTransport/RabbitMqTransport/Configuration/RabbitMqBusFactoryConfigurator.cs:line 165 at MassTransit.Configuration.BusRegistrationContext.ConfigureTheEndpoints[T](IEnumerable`1 endpoints, IEndpointNameFormatter endpointNameFormatter, Func`2 getEndpointDefinitionByName, IReceiveConfigurator`1 configurator, IReceiveConfigurator`1 instanceConfigurator) in /_/src/MassTransit/DependencyInjection/Configuration/BusRegistrationContext.cs:line 173 at MassTransit.Configuration.BusRegistrationContext.ConfigureEndpoints[T](IReceiveConfigurator`1 configurator, IEndpointNameFormatter endpointNameFormatter, Action`1 configureFilter) in /_/src/MassTransit/DependencyInjection/Configuration/BusRegistrationContext.cs:line 147 at MassTransit.Configuration.BusRegistrationContext.ConfigureEndpoints[T](IReceiveConfigurator`1 configurator, IEndpointNameFormatter endpointNameFormatter) in /_/src/MassTransit/DependencyInjection/Configuration/BusRegistrationContext.cs:line 28 at MassTransit.RegistrationContextExtensions.ConfigureEndpoints[T](IBusFactoryConfigurator`1 configurator, IBusRegistrationContext registration, IEndpointNameFormatter endpointNameFormatter) in /_/src/MassTransit/Configuration/RegistrationContextExtensions.cs:line 23 at Program.<>c__DisplayClass0_0.<
$>b__4(IBusRegistrationContext context, IRabbitMqBusFactoryConfigurator c) in /Users/local/Projects/Demo/SuuCat/src/StateMachines/SagaOrchestrationStateMachine/Program.cs:line 37 at MassTransit.Configuration.TransportRegistrationBusFactory`1.CreateBus[T,TConfigurator](T configurator, IBusRegistrationContext context, Action`2 configure, IEnumerable`1 specifications) in /_/src/MassTransit/DependencyInjection/Configuration/TransportRegistrationBusFactory.cs:line 36 at MassTransit.RabbitMqTransport.Configuration.RabbitMqRegistrationBusFactory.CreateBus(IBusRegistrationContext context, IEnumerable`1 specifications, String busName) in /_/src/Transports/MassTransit.RabbitMqTransport/RabbitMqTransport/Configuration/RabbitMqRegistrationBusFactory.cs:line 71 at MassTransit.Configuration.ServiceCollectionBusConfigurator.CreateBus[T](T busFactory, IServiceProvider provider) in /_/src/MassTransit/DependencyInjection/Configuration/ServiceCollectionBusConfigurator.cs:line 116 at MassTransit.Configuration.ServiceCollectionBusConfigurator.<>c__DisplayClass3_0`1.b__0(IServiceProvider provider) in /_/src/MassTransit/DependencyInjection/Configuration/ServiceCollectionBusConfigurator.cs:line 78 at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType) at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory) at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at MassTransit.Configuration.ServiceCollectionBusConfigurator.<>c__3`1.b__3_1(IServiceProvider provider) in /_/src/MassTransit/DependencyInjection/Configuration/ServiceCollectionBusConfigurator.cs:line 80 at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType) at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory) at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken) at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token) at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token) at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host) at Program.
$(String[] args) in /Users/local/Projects/Demo/SuuCat/src/StateMachines/SagaOrchestrationStateMachine/Program.cs:line 75 `
bkershaw commented 7 months ago

I resolved the error by changing the access modifiers of the state properties from private to public in the OrderStateMachine class.

Essentially MassTransit TransitionExtension class could not access the State properties such as "Name" resulting in a Null Reference exception.

Before

public class OrderStateMachine : MassTransitStateMachine<OrderStateInstance>
{
    private readonly ILogger _logger;

    // Commands
    private Event<ICreateOrderMessage> CreateOrderMessage { get; set; }

    // Events
    private Event<IStockReservedEvent> StockReservedEvent { get; set; }
    private Event<IStockReservationFailedEvent> StockReservationFailedEvent { get; set; }
    private Event<IPaymentCompletedEvent> PaymentCompletedEvent { get; set; }
    private Event<IPaymentFailedEvent> PaymentFailedEvent { get; set; }

    // States
    private State OrderCreated { get; set; }
    private State StockReserved { get; set; }
    private State StockReservationFailed { get; set; }
    private State PaymentCompleted { get; set; }
    private State PaymentFailed { get; set; }

    //  remaining code
}

After

public class OrderStateMachine : MassTransitStateMachine<OrderStateInstance>
{
    private readonly ILogger _logger;

    // Commands
    private Event<ICreateOrderMessage> CreateOrderMessage { get; set; }

    // Events
    public Event<IStockReservedEvent> StockReservedEvent { get; set; }
    public Event<IStockReservationFailedEvent> StockReservationFailedEvent { get; set; }
    public Event<IPaymentCompletedEvent> PaymentCompletedEvent { get; set; }
    public Event<IPaymentFailedEvent> PaymentFailedEvent { get; set; }

    // States
    public State OrderCreated { get; set; } 
    public State StockReserved { get; set; }
    public State StockReservationFailed { get; set; }
    public State PaymentCompleted { get; set; }
    public State PaymentFailed { get; set; }

    //  remaining code
ebubekirdinc commented 7 months ago

That was a good catch. I've made a new update based on your findings. Thanks.