/// <summary> /// Uses the Brighter In-Memory Inbox to store messages received to support once-only messaging and diagnostics /// Advantages: Fast and no additional infrastructure required /// Disadvantages: The inbox will not survive restarts, so messages will not be de-duped if received after a restart. /// The inbox will not work across threads/processes so only works with a single performer/consumer. /// Registers singletons with the service collection: /// - InMemoryInboxSync - what messages have we received /// - InMemoryInboxAsync - what messages have we recived (async pipeline compatible) /// </summary> /// <param name="brighterBuilder"></param> /// <returns></returns> public static IBrighterBuilder UseInMemoryInbox(this IBrighterBuilder brighterBuilder) { brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmAnInboxSync), _ => new InMemoryInbox(), ServiceLifetime.Singleton)); brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmAnInboxAsync), _ => new InMemoryInbox(), ServiceLifetime.Singleton)); return(brighterBuilder); }
public static IBrighterBuilder UsePostgreSqlOutbox( this IBrighterBuilder brighterBuilder, PostgreSqlOutboxConfiguration configuration, Type connectionProvider = null, ServiceLifetime serviceLifetime = ServiceLifetime.Singleton) { if (brighterBuilder is null) { throw new ArgumentNullException($"{nameof(brighterBuilder)} cannot be null.", nameof(brighterBuilder)); } if (configuration is null) { throw new ArgumentNullException($"{nameof(configuration)} cannot be null.", nameof(configuration)); } brighterBuilder.Services.AddSingleton <PostgreSqlOutboxConfiguration>(configuration); if (connectionProvider is object) { if (!typeof(IPostgreSqlConnectionProvider).IsAssignableFrom(connectionProvider)) { throw new Exception($"Unable to register provider of type {connectionProvider.GetType().Name}. Class does not implement interface {nameof(IPostgreSqlConnectionProvider)}."); } brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IPostgreSqlConnectionProvider), connectionProvider, serviceLifetime)); } brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmAnOutboxSync <Message>), BuildPostgreSqlOutboxSync, serviceLifetime)); return(brighterBuilder); }
/// <summary> /// Use this transaction provider to ensure that the Outbox and the Entity Store are correct /// </summary> /// <param name="brighterBuilder">Allows extension method</param> /// <param name="connectionProvider">What is the tyoe of the connection provider</param> /// <param name="serviceLifetime">What is the lifetime of registered interfaces</param> /// <returns>Allows fluent syntax</returns> /// This is paired with Use Outbox (above) when required /// Registers the following /// -- IAmABoxTransactionConnectionProvider: the provider of a connection for any existing transaction public static IBrighterBuilder UseMsSqlTransactionConnectionProvider( this IBrighterBuilder brighterBuilder, Type connectionProvider, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped) { brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmABoxTransactionConnectionProvider), connectionProvider, serviceLifetime)); return(brighterBuilder); }
/// <summary> /// An external bus is the use of Message Oriented Middleware (MoM) to dispatch a message between a producer and a consumer. The assumption is that this /// is being used for inter-process communication, for example the work queue pattern for distributing work, or between microservicves /// Registers singletons with the service collection :- /// - Producer - the Gateway wrapping access to Middleware /// - UseRpc - do we want to use Rpc i.e. a command blocks waiting for a response, over middleware /// </summary> /// <param name="brighterBuilder">The Brighter builder to add this option to</param> /// <param name="producerRegistry">The collection of producers - clients that connect to a specific transport</param> /// <param name="useRequestResponseQueues">Add support for RPC over MoM by using a reply queue</param> /// <param name="replyQueueSubscriptions">Reply queue subscription</param> /// <returns>The Brighter builder to allow chaining of requests</returns> public static IBrighterBuilder UseExternalBus(this IBrighterBuilder brighterBuilder, IAmAProducerRegistry producerRegistry, bool useRequestResponseQueues = false, IEnumerable <Subscription> replyQueueSubscriptions = null) { brighterBuilder.Services.AddSingleton <IAmAProducerRegistry>(producerRegistry); brighterBuilder.Services.AddSingleton <IUseRpc>(new UseRpc(useRequestResponseQueues, replyQueueSubscriptions)); return(brighterBuilder); }
public static IBrighterBuilder UseEventStoreOutbox( this IBrighterBuilder brighterBuilder, IEventStoreConnection connection, ServiceLifetime serviceLifetime = ServiceLifetime.Singleton) { brighterBuilder.Services.AddSingleton <IEventStoreConnection>(connection); brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmAnOutboxSync <Message>), BuildEventStoreOutbox, serviceLifetime)); brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmAnOutboxAsync <Message>), BuildEventStoreOutbox, serviceLifetime)); return(brighterBuilder); }
/// <summary> /// Use MsSql for the Outbox /// </summary> /// <param name="brighterBuilder">Allows extension method syntax</param> /// <param name="configuration">The connection for the Db and name of the Outbox table</param> /// <param name="connectionProvider">What is the type for the class that lets us obtain connections for the Sqlite database</param> /// <param name="serviceLifetime">What is the lifetime of the services that we add</param> /// <returns>Allows fluent syntax</returns> /// -- Registers the following /// -- MsSqlConfigutation: connection string and outbox name /// -- IMsSqlConnectionProvider: lets us get a connection for the outbox that matches the entity store /// -- IAmAnOutbox<Message>: an outbox to store messages we want to send /// -- IAmAnOutboxAsync<Message>: an outbox to store messages we want to send /// -- IAmAnOutboxViewer<Message>: Lets us read the entries in the outbox /// -- IAmAnOutboxViewerAsync<Message>: Lets us read the entries in the outbox public static IBrighterBuilder UseMsSqlOutbox( this IBrighterBuilder brighterBuilder, MsSqlConfiguration configuration, Type connectionProvider, ServiceLifetime serviceLifetime = ServiceLifetime.Singleton) { brighterBuilder.Services.AddSingleton <MsSqlConfiguration>(configuration); brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IMsSqlConnectionProvider), connectionProvider, serviceLifetime)); brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmAnOutboxSync <Message>), BuildMsSqlOutbox, serviceLifetime)); brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmAnOutboxAsync <Message>), BuildMsSqlOutbox, serviceLifetime)); return(brighterBuilder); }
public static IBrighterBuilder UseDynamoDbOutbox( this IBrighterBuilder brighterBuilder, IAmazonDynamoDB connection, DynamoDbConfiguration configuration, ServiceLifetime serviceLifetime = ServiceLifetime.Singleton) { brighterBuilder.Services.AddSingleton <DynamoDbConfiguration>(configuration); brighterBuilder.Services.AddSingleton <IAmazonDynamoDB>(connection); brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmAnOutboxSync <Message>), BuildDynamoDbOutbox, serviceLifetime)); brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmAnOutboxAsync <Message>), BuildDynamoDbOutbox, serviceLifetime)); return(brighterBuilder); }
/// <summary> /// Use a timer based outbox sweeper as a Hosted Service. /// </summary> /// <param name="brighterBuilder">The Brighter Builder</param> /// <param name="timedOutboxSweeperOptionsAction">Configuration actions for the Timed outbox Sweeper <see cref="TimedOutboxSweeper"/></param> /// <returns>The Brighter Builder</returns> public static IBrighterBuilder UseOutboxSweeper(this IBrighterBuilder brighterBuilder, Action <TimedOutboxSweeperOptions> timedOutboxSweeperOptionsAction = null) { var options = new TimedOutboxSweeperOptions(); timedOutboxSweeperOptionsAction?.Invoke(options); brighterBuilder.Services.AddSingleton <TimedOutboxSweeperOptions>(options); brighterBuilder.Services.AddHostedService <TimedOutboxSweeper>(); return(brighterBuilder); }
/// <summary> /// Use an external Brighter Outbox to store messages Posted to another process (evicts based on age and size). /// Advantages: By using the same Db to store both any state changes for your app, and outgoing messages you can create a transaction that spans both /// your state change and writing to an outbox [use DepositPost to store]. Then a sweeper process can look for message not flagged as sent and send them. /// For low latency just send after the transaction with ClearOutbox, for higher latency just let the sweeper run in the background. /// The outstanding messages dispatched this way can be sent from any producer that runs a sweeper process and so it not tied to the lifetime of the /// producer, offering guaranteed, at least once, delivery. /// NOTE: there may be a database specific Use*OutBox available. If so, use that in preference to this generic method /// If not null, registers singletons with the service collection :- /// - IAmAnOutboxSync - what messages have we posted /// - ImAnOutboxAsync - what messages have we posted (async pipeline compatible) /// </summary> /// <param name="brighterBuilder">The Brighter builder to add this option to</param> /// <param name="outbox">The outbox provider - if your outbox supports both sync and async options, just provide this and we will register both</param> /// <returns></returns> public static IBrighterBuilder UseExternalOutbox(this IBrighterBuilder brighterBuilder, IAmAnOutbox <Message> outbox = null) { if (outbox is IAmAnOutboxSync <Message> ) { brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmAnOutboxSync <Message>), _ => outbox, ServiceLifetime.Singleton)); } if (outbox is IAmAnOutboxAsync <Message> ) { brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmAnOutboxAsync <Message>), _ => outbox, ServiceLifetime.Singleton)); } return(brighterBuilder); }
/// <summary> /// Uses an external Brighter Inbox to record messages received to allow "once only" or diagnostics (how did we get here?) /// Advantages: by using an external inbox then you can share "once only" across multiple threads/processes and support a competing consumer /// model; an internal inbox is useful for testing but outside of single consumer scenarios won't work as intended /// If not null, registers singletons with the service collecion :- /// - IAmAnInboxSync - what messages have we received /// - IAmAnInboxAsync - what messages have we received (async pipeline compatible) /// </summary> /// <param name="brighterBuilder">Extension method to support a fluent interface</param> /// <param name="inbox">The external inbox to use</param> /// <param name="inboxConfiguration">If this is null, configure by hand, if not, will auto-add inbox to handlers</param> /// <returns></returns> public static IBrighterBuilder UseExternalInbox( this IBrighterBuilder brighterBuilder, IAmAnInbox inbox, InboxConfiguration inboxConfiguration = null, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped) { if (inbox is IAmAnInboxSync) { brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmAnInboxSync), _ => inbox, serviceLifetime)); } if (inbox is IAmAnInboxAsync) { brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmAnInboxAsync), _ => inbox, serviceLifetime)); } if (inboxConfiguration != null) { brighterBuilder.Services.AddSingleton <InboxConfiguration>(inboxConfiguration); } return(brighterBuilder); }
/// <summary> /// Use this transaction provider to ensure that the Outbox and the Entity Store are correct /// </summary> /// <param name="brighterBuilder">Allows extension method</param> /// <param name="connectionProvider">What is the type of the connection provider. Must implement interface IPostgreSqlTransactionConnectionProvider</param> /// <param name="serviceLifetime">What is the lifetime of registered interfaces</param> /// <returns>Allows fluent syntax</returns> /// This is paired with Use Outbox (above) when required /// Registers the following /// -- IAmABoxTransactionConnectionProvider: the provider of a connection for any existing transaction public static IBrighterBuilder UsePostgreSqlTransactionConnectionProvider( this IBrighterBuilder brighterBuilder, Type connectionProvider, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped) { if (brighterBuilder is null) { throw new ArgumentNullException($"{nameof(brighterBuilder)} cannot be null.", nameof(brighterBuilder)); } if (connectionProvider is null) { throw new ArgumentNullException($"{nameof(connectionProvider)} cannot be null.", nameof(connectionProvider)); } if (!typeof(IPostgreSqlTransactionConnectionProvider).IsAssignableFrom(connectionProvider)) { throw new Exception($"Unable to register provider of type {connectionProvider.GetType().Name}. Class does not implement interface {nameof(IPostgreSqlTransactionConnectionProvider)}."); } brighterBuilder.Services.Add(new ServiceDescriptor(typeof(IAmABoxTransactionConnectionProvider), connectionProvider, serviceLifetime)); return(brighterBuilder); }
/// <summary> /// Configure a Feature Switch registry to control handlers to be feature switched at runtime /// </summary> /// <param name="brighterBuilder">The Brighter builder to add this option to</param> /// <param name="featureSwitchRegistry">The registry for handler Feature Switches</param> /// <returns>The Brighter builder to allow chaining of requests</returns> public static IBrighterBuilder UseFeatureSwitches(this IBrighterBuilder brighterBuilder, IAmAFeatureSwitchRegistry featureSwitchRegistry) { brighterBuilder.Services.AddSingleton(featureSwitchRegistry); return(brighterBuilder); }