public static ISagaConfigurator <TS, TD> UseRabbitMQTransport <TS, TD>(this ISagaConfigurator <TS, TD> sagaConfigurator) where TS : Saga <TD> where TD : SagaState { var sagaType = typeof(TS); var messageHandlerType = typeof(IHandleMessage <>).GetGenericTypeDefinition(); var interfaces = sagaType.GetInterfaces(); foreach (var i in interfaces) { if (!i.IsGenericType) { continue; } var openGeneric = i.GetGenericTypeDefinition(); if (!openGeneric.IsAssignableFrom(messageHandlerType)) { continue; } var messageType = i.GetGenericArguments().First(); sagaConfigurator.Services.AddSingleton(typeof(ISubscriber), typeof(RabbitSubscriber <>).MakeGenericType(messageType)); } return(sagaConfigurator); }
public static ISagaConfigurator <TS, TD> UseInMemoryTransport <TS, TD>(this ISagaConfigurator <TS, TD> sagaConfigurator) where TS : Saga <TD> where TD : SagaState { var sagaType = typeof(TS); var messageHandlerType = typeof(IHandleMessage <>).GetGenericTypeDefinition(); var interfaces = sagaType.GetInterfaces(); foreach (var i in interfaces) { if (!i.IsGenericType) { continue; } var openGeneric = i.GetGenericTypeDefinition(); if (!openGeneric.IsAssignableFrom(messageHandlerType)) { continue; } var messageType = i.GetGenericArguments().First(); var registerMessageMethod = RawRegisterMessageMethod.MakeGenericMethod(messageType); registerMessageMethod.Invoke(null, new[] { sagaConfigurator.Services }); } return(sagaConfigurator); }
public MessageRetrySagaConfigurationObserver(ISagaConfigurator <TSaga> configurator, CancellationToken cancellationToken, Action <IRetryConfigurator> configure) { _configurator = configurator; _cancellationToken = cancellationToken; _configure = configure; }
public static ISagaConfigurator <TS, TD> UseRabbitMQTransport <TS, TD>(this ISagaConfigurator <TS, TD> sagaConfigurator, RabbitConfiguration config) where TS : Saga <TD> where TD : SagaState { var sagaType = typeof(TS); var messageHandlerType = typeof(IHandleMessage <>).GetGenericTypeDefinition(); var interfaces = sagaType.GetInterfaces(); foreach (var i in interfaces) { if (!i.IsGenericType) { continue; } var openGeneric = i.GetGenericTypeDefinition(); if (!openGeneric.IsAssignableFrom(messageHandlerType)) { continue; } var messageType = i.GetGenericArguments().First(); sagaConfigurator.Services.AddSingleton(typeof(ISubscriber), typeof(RabbitSubscriber <>).MakeGenericType(messageType)); } if (!_initialized) { var encoder = new JsonEncoder(); sagaConfigurator.Services.AddSingleton <IEncoder>(encoder); sagaConfigurator.Services.AddSingleton <IDecoder>(encoder); sagaConfigurator.Services.AddSingleton <IQueueReferenceFactory, QueueReferenceFactory>(); sagaConfigurator.Services.AddSingleton <IMessageParser, MessageParser>(); sagaConfigurator.Services.AddSingleton <IPublisher, RabbitPublisher>(); sagaConfigurator.Services.AddSingleton <IPublisherChannelFactory, PublisherChannelFactory>(); sagaConfigurator.Services.AddSingleton <IConnectionFactory>(ctx => { var connectionFactory = new ConnectionFactory() { HostName = config.HostName, UserName = config.UserName, Password = config.Password, Port = AmqpTcpEndpoint.UseDefaultPort, DispatchConsumersAsync = true }; return(connectionFactory); }); sagaConfigurator.Services.AddSingleton <IBusConnection, RabbitPersistentConnection>(); _initialized = true; } return(sagaConfigurator); }
protected override void ConfigureSaga(IReceiveEndpointConfigurator endpointConfigurator, ISagaConfigurator <AllocationState> sagaConfigurator) { // to resolve the duplicate key error, AllocationCreated, ReleaseRequested endpointConfigurator.UseMessageRetry(configurator => configurator.Interval(3, 1000)); // this holds the messages until the persistence part of those messages completed endpointConfigurator.UseInMemoryOutbox(); }
public static ISagaConfigurator <TS, TD> UseInMemoryPersistence <TS, TD>(this ISagaConfigurator <TS, TD> sagaConfigurator) where TS : Saga <TD> where TD : SagaState { sagaConfigurator.Services.AddSingleton(typeof(ISagaStateRepository), typeof(InMemorySagaStateRepository)); sagaConfigurator.Services.AddSingleton <IUnitOfWork, InMemoryUnitOfWork>(); return(sagaConfigurator); }
protected override void ConfigureSaga(IReceiveEndpointConfigurator endpointConfigurator, ISagaConfigurator <OrderState> sagaConfigurator) { // var partition = endpointConfigurator.CreatePartitioner(8); // sagaConfigurator.Message<OrderSubmitted>(m => m.UsePartitioner(partition, m => m.Message.CustomerNumber)); endpointConfigurator.UseMessageRetry(r => r.Intervals(500, 5000, 10000)); endpointConfigurator.UseInMemoryOutbox(); }
public void StateMachineSagaConfigured <TInstance>(ISagaConfigurator <TInstance> configurator, SagaStateMachine <TInstance> stateMachine) where TInstance : class, ISaga, SagaStateMachineInstance { All(observer => { observer.StateMachineSagaConfigured(configurator, stateMachine); return(true); }); }
public void SagaConfigured <TSaga>(ISagaConfigurator <TSaga> configurator) where TSaga : class, ISaga { All(observer => { observer.SagaConfigured(configurator); return(true); }); }
/// <summary> /// Includes an outbox in the consume filter path, which delays outgoing messages until the return path /// of the pipeline returns to the outbox filter. At this point, the message execution pipeline should be /// nearly complete with only the ack remaining. If an exception is thrown, the messages are not sent/published. /// </summary> /// <param name="configurator"></param> /// <param name="configure">Configure the outbox</param> public static void UseInMemoryOutbox <TSaga>(this ISagaConfigurator <TSaga> configurator, Action <IOutboxConfigurator> configure = default) where TSaga : class, ISaga { if (configurator == null) { throw new ArgumentNullException(nameof(configurator)); } var observer = new InMemoryOutboxSagaConfigurationObserver <TSaga>(configurator, configure); configurator.ConnectSagaConfigurationObserver(observer); }
/// <summary> /// Limits the number of concurrent messages consumed by the saga, regardless of message type. /// </summary> /// <param name="configurator"></param> /// <param name="concurrentMessageLimit">The concurrent message limit for all message types for the saga</param> public static void UseConcurrentMessageLimit <TSaga>(this ISagaConfigurator <TSaga> configurator, int concurrentMessageLimit) where TSaga : class, ISaga { if (configurator == null) { throw new ArgumentNullException(nameof(configurator)); } var observer = new ConcurrencyLimitSagaConfigurationObserver <TSaga>(configurator, concurrentMessageLimit); configurator.ConnectSagaConfigurationObserver(observer); }
/// <summary> /// Configure scheduled redelivery for the saga, regardless of message type. /// </summary> /// <param name="configurator"></param> /// <param name="configure"></param> public static void UseScheduledRedelivery <TSaga>(this ISagaConfigurator <TSaga> configurator, Action <IRetryConfigurator> configure) where TSaga : class, ISaga { if (configurator == null) { throw new ArgumentNullException(nameof(configurator)); } var observer = new MessageRedeliverySagaConfigurationObserver <TSaga>(configurator, configure); configurator.ConnectSagaConfigurationObserver(observer); }
public static ISagaConfigurator <TS, TD> UseInMemoryTransport <TS, TD>(this ISagaConfigurator <TS, TD> sagaConfigurator) where TS : Saga <TD> where TD : SagaState { var messageTypes = SagaUtils <TS, TD> .GetHandledMessageTypes(); foreach (var messageType in messageTypes) { var registerMessageMethod = RawRegisterMessageMethod.MakeGenericMethod(messageType); registerMessageMethod.Invoke(null, new[] { sagaConfigurator.Services }); } return(sagaConfigurator); }
public static ISagaConfigurator <TS, TD> UseRabbitMQTransport <TS, TD>(this ISagaConfigurator <TS, TD> sagaConfigurator) where TS : Saga <TD> where TD : SagaState { var messageTypes = SagaUtils <TS, TD> .GetHandledMessageTypes(); foreach (var messageType in messageTypes) { sagaConfigurator.Services.AddBusSubscriber( typeof(RabbitSubscriber <>).MakeGenericType(messageType)); } return(sagaConfigurator); }
public static ISagaConfigurator <TS, TD> UseKafkaTransport <TS, TD>(this ISagaConfigurator <TS, TD> sagaConfigurator) where TS : Saga <TD> where TD : SagaState { var messageTypes = typeof(TS).GetHandledMessageTypes(); foreach (var messageType in messageTypes) { sagaConfigurator.Services.AddBusSubscriber( typeof(KafkaSubscriber <>).MakeGenericType(messageType)); sagaConfigurator.Services.AddSingleton(typeof(IInfrastructureCreator), typeof(KafkaInfrastructureCreator <>).MakeGenericType(messageType)); } return(sagaConfigurator); }
/// <summary> /// Configures the message retry for the consumer consumer, regardless of message type. /// </summary> /// <param name="configurator"></param> /// <param name="busFactoryConfigurator"> /// The bus factory configurator, to connect the observer, to cancel retries if the bus is stopped /// </param> /// <param name="configure"></param> public static void UseMessageRetry <TSaga>(this ISagaConfigurator <TSaga> configurator, IBusFactoryConfigurator busFactoryConfigurator, Action <IRetryConfigurator> configure) where TSaga : class, ISaga { if (configurator == null) { throw new ArgumentNullException(nameof(configurator)); } var retryObserver = new RetryBusObserver(); busFactoryConfigurator.ConnectBusObserver(retryObserver); var observer = new MessageRetrySagaConfigurationObserver <TSaga>(configurator, retryObserver.Stopping, configure); configurator.ConnectSagaConfigurationObserver(observer); }
/// <summary> /// Limits the number of concurrent messages consumed by the saga, regardless of message type. /// </summary> /// <param name="configurator"></param> /// <param name="concurrentMessageLimit">The concurrent message limit for all message types for the saga</param> /// <param name="managementEndpointConfigurator">A management endpoint configurator to support runtime adjustment</param> /// <param name="id">An identifier for the concurrency limit to allow selective adjustment</param> public static void UseConcurrentMessageLimit <TSaga>(this ISagaConfigurator <TSaga> configurator, int concurrentMessageLimit, IManagementEndpointConfigurator managementEndpointConfigurator, string id = null) where TSaga : class, ISaga { if (configurator == null) { throw new ArgumentNullException(nameof(configurator)); } var observer = new ConcurrencyLimitSagaConfigurationObserver <TSaga>(configurator, concurrentMessageLimit, id); configurator.ConnectSagaConfigurationObserver(observer); managementEndpointConfigurator.Instance(observer.Limiter, x => { x.UseConcurrentMessageLimit(1); x.Message <SetConcurrencyLimit>(m => m.UseRetry(r => r.None())); }); }
public static ISagaConfigurator <TS, TD> UseInMemoryTransport <TS, TD>(this ISagaConfigurator <TS, TD> sagaConfigurator) where TS : Saga <TD> where TD : SagaState { var sagaType = typeof(TS); var messageHandlerType = typeof(IHandleMessage <>).GetGenericTypeDefinition(); var interfaces = sagaType.GetInterfaces(); foreach (var i in interfaces) { if (!i.IsGenericType) { continue; } var openGeneric = i.GetGenericTypeDefinition(); if (!openGeneric.IsAssignableFrom(messageHandlerType)) { continue; } var messageType = i.GetGenericArguments().First(); var rawMethod = typeof(Channel).GetMethod(nameof(Channel.CreateUnbounded), Array.Empty <Type>()); var method = rawMethod.MakeGenericMethod(messageType); dynamic channel = method.Invoke(null, null); sagaConfigurator.Services.AddSingleton(typeof(Channel <>).MakeGenericType(messageType), (object)channel); sagaConfigurator.Services.AddSingleton(typeof(ChannelWriter <>).MakeGenericType(messageType), (object)channel.Writer); sagaConfigurator.Services.AddSingleton(typeof(ChannelReader <>).MakeGenericType(messageType), (object)channel.Reader); sagaConfigurator.Services.AddSingleton(typeof(ISubscriber), typeof(InMemorySubscriber <>).MakeGenericType(messageType)); } sagaConfigurator.Services.AddSingleton <IPublisher, InMemoryPublisher>() .AddSingleton <IChannelFactory, ChannelFactory>(); return(sagaConfigurator); }
public static ISagaConfigurator <TS, TD> UseMongoPersistence <TS, TD>( this ISagaConfigurator <TS, TD> sagaConfigurator, MongoConfiguration config) where TS : Saga <TD> where TD : SagaState { sagaConfigurator.Services .AddSingleton <IMongoClient>(ctx => new MongoClient(connectionString: config.ConnectionString)) .AddSingleton(ctx => { var client = ctx.GetRequiredService <IMongoClient>(); var database = client.GetDatabase(config.DbName); return(database); }) .AddSingleton <ISerializer, JsonSerializer>() .AddSingleton <IDbContext, DbContext>() .AddSingleton <IUnitOfWork, MongoUnitOfWork>() .AddSingleton(config.RepositoryOptions) .AddSingleton <ISagaStateRepository, MongoSagaStateRepository>() .AddSingleton <IOutboxRepository, OutboxRepository>(); return(sagaConfigurator); }
public void SagaConfigured <TSaga>(ISagaConfigurator <TSaga> configurator) where TSaga : class, ISaga { _sagaObservers.SagaConfigured(configurator); }
public void StateMachineSagaConfigured <TInstance>(ISagaConfigurator <TInstance> configurator, SagaStateMachine <TInstance> stateMachine) where TInstance : class, ISaga, SagaStateMachineInstance { }
public void SagaConfigured <T>(ISagaConfigurator <T> configurator) where T : class, ISaga { }
public void SagaConfigured <TSaga>(ISagaConfigurator <TSaga> configurator) where TSaga : class, ISaga { _busEndpointConfiguration.Consume.Configurator.SagaConfigured(configurator); }
protected override void ConfigureSagaTransport <TS, TD>(ISagaConfigurator <TS, TD> cfg) => cfg.UseInMemoryTransport();
protected override void ConfigureSagaTransport <TS, TD>(ISagaConfigurator <TS, TD> cfg) => cfg.UseRabbitMQTransport();
protected override void ConfigureSaga(IReceiveEndpointConfigurator endpointConfigurator, ISagaConfigurator <OrderState> sagaConfigurator) { endpointConfigurator.UseMessageRetry(r => r.Intervals(500, 5000, 10000)); endpointConfigurator.UseInMemoryOutbox(); }
void ISagaConfigurationObserver.SagaConfigured <TSaga>(ISagaConfigurator <TSaga> configurator) { }
public void StateMachineSagaConfigured <TInstance>(ISagaConfigurator <TInstance> configurator, SagaStateMachine <TInstance> stateMachine) where TInstance : class, ISaga, SagaStateMachineInstance { _sagaObservers.StateMachineSagaConfigured(configurator, stateMachine); }
protected override void ConfigureSaga(IReceiveEndpointConfigurator endpointConfigurator, ISagaConfigurator <DiscoveryPingState> sagaConfigurator) { var partition = endpointConfigurator.CreatePartitioner(Environment.ProcessorCount); sagaConfigurator.Message <PingReceived>(x => x.UsePartitioner(partition, m => m.Message.CorrelationId)); sagaConfigurator.Message <PingAcknowledged>(x => x.UsePartitioner(partition, m => m.Message.CorrelationId)); }
public void SagaConfigured <TSaga>(ISagaConfigurator <TSaga> configurator) where TSaga : class, ISaga { _configurator.SagaConfigured(configurator); }