From 76cc7cbc0330637543e6707ad6485df247b4e05a Mon Sep 17 00:00:00 2001 From: Rafael Andrade Date: Fri, 14 Nov 2025 10:08:02 +0000 Subject: [PATCH] Add postgres docs --- .../Extensions/ConsumerBuilderExtensions.cs | 65 +++++++- .../Extensions/FluentBrighterExtensions.cs | 13 ++ .../PostgresInboxBuilderExtensions.cs | 12 ++ ...MessageProducerFactoryBuilderExtensions.cs | 37 +++++ .../PostgresOutboxBuilderExtensions.cs | 12 ++ .../PostgresPublicationBuilderExtensions.cs | 65 +++++++- .../PostgresSubscriptionBuilderExtensions.cs | 116 ++++++++++++-- .../Extensions/ProducersExtensions.cs | 64 +++++++- .../PostgresConfigurator.cs | 53 ++++++- .../PostgresInboxBuilder.cs | 22 +++ .../PostgresMessageProducerFactoryBuilder.cs | 22 +++ .../PostgresOutboxBuilder.cs | 29 ++++ .../PostgresPublicationBuilder.cs | 90 ++++++++++- .../PostgresSubscriptionBuilder.cs | 150 ++++++++++++++++++ .../PostgresSubscriptionConfigurator.cs | 31 +++- 15 files changed, 751 insertions(+), 30 deletions(-) diff --git a/src/Fluent.Brighter.Postgres/Extensions/ConsumerBuilderExtensions.cs b/src/Fluent.Brighter.Postgres/Extensions/ConsumerBuilderExtensions.cs index f2825ad..4decf4d 100644 --- a/src/Fluent.Brighter.Postgres/Extensions/ConsumerBuilderExtensions.cs +++ b/src/Fluent.Brighter.Postgres/Extensions/ConsumerBuilderExtensions.cs @@ -7,11 +7,28 @@ namespace Fluent.Brighter; +/// +/// Provides extension methods for to configure PostgreSQL-based message consumers. +/// These extensions enable easy setup of PostgreSQL subscriptions, inbox patterns, and channel factories. +/// public static class ConsumerBuilderExtensions { + /// + /// Adds a pre-configured PostgreSQL subscription to the consumer builder. + /// + /// The instance to configure. + /// The pre-configured to add. + /// The instance for method chaining. public static ConsumerBuilder AddPostgresSubscription(this ConsumerBuilder builder, PostgresSubscription subscription) => builder.AddSubscription(subscription); + /// + /// Adds a PostgreSQL subscription to the consumer builder using a configuration action. + /// This method creates a new , applies the configuration, and builds the subscription. + /// + /// The instance to configure. + /// An action that configures the with subscription settings. + /// The instance for method chaining. public static ConsumerBuilder AddPostgresSubscription(this ConsumerBuilder builder, Action configure) { @@ -20,6 +37,15 @@ public static ConsumerBuilder AddPostgresSubscription(this ConsumerBuilder build return builder.AddSubscription(sub.Build()); } + /// + /// Adds a PostgreSQL subscription for a specific request type to the consumer builder. + /// This method automatically configures the subscription with the specified type + /// and then applies additional configuration provided by the action. + /// + /// The type of request/message that this subscription will handle. Must implement . + /// The instance to configure. + /// An action that configures the with additional settings. + /// The instance for method chaining. public static ConsumerBuilder AddPostgresSubscription(this ConsumerBuilder builder, Action configure) where TRequest : class, IRequest @@ -30,7 +56,14 @@ public static ConsumerBuilder AddPostgresSubscription(this ConsumerBui return builder.AddSubscription(sub.Build()); } - + /// + /// Configures the consumer to use a PostgreSQL inbox pattern using a database configuration builder. + /// The inbox pattern ensures message deduplication and idempotent message processing by storing + /// information about received messages in PostgreSQL. + /// + /// The instance to configure. + /// An action that configures the with connection details. + /// The instance for method chaining. public static ConsumerBuilder UsePostgresInbox(this ConsumerBuilder builder, Action configure) { @@ -39,9 +72,25 @@ public static ConsumerBuilder UsePostgresInbox(this ConsumerBuilder builder, return builder.UsePostgresInbox(configuration.Build()); } + /// + /// Configures the consumer to use a PostgreSQL inbox pattern using a pre-configured database configuration. + /// The inbox pattern ensures message deduplication and idempotent message processing by storing + /// information about received messages in PostgreSQL. + /// + /// The instance to configure. + /// The pre-configured relational database configuration containing connection details. + /// The instance for method chaining. public static ConsumerBuilder UsePostgresInbox(this ConsumerBuilder builder, IAmARelationalDatabaseConfiguration configuration) => builder.UsePostgresInbox(cfg => cfg.SetConfiguration(configuration)); + /// + /// Configures the consumer to use a PostgreSQL inbox pattern using a custom inbox builder configuration. + /// This method provides the most flexibility by allowing direct configuration of the , + /// including custom connection providers and other advanced settings. + /// + /// The instance to configure. + /// An action that configures the with inbox settings. + /// The instance for method chaining. public static ConsumerBuilder UsePostgresInbox(this ConsumerBuilder builder, Action configure) { var inbox = new PostgresInboxBuilder(); @@ -49,6 +98,13 @@ public static ConsumerBuilder UsePostgresInbox(this ConsumerBuilder builder, Act return builder.SetInbox(cfg => cfg.SetInbox(inbox.Build())); } + /// + /// Adds a PostgreSQL channel factory to the consumer builder using a database configuration builder. + /// Channel factories are responsible for creating message channels that consume messages from PostgreSQL queues. + /// + /// The instance to configure. + /// An action that configures the with connection details. + /// The instance for method chaining. public static ConsumerBuilder AddPostgresChannelFactory(this ConsumerBuilder builder, Action configure) { @@ -57,6 +113,13 @@ public static ConsumerBuilder AddPostgresChannelFactory(this ConsumerBuilder bui return builder.AddPostgresChannelFactory(configuration.Build()); } + /// + /// Adds a PostgreSQL channel factory to the consumer builder using a pre-configured database configuration. + /// Channel factories are responsible for creating message channels that consume messages from PostgreSQL queues. + /// + /// The instance to configure. + /// The pre-configured relational database configuration containing connection details. + /// The instance for method chaining. public static ConsumerBuilder AddPostgresChannelFactory(this ConsumerBuilder builder, RelationalDatabaseConfiguration configuration) { return builder diff --git a/src/Fluent.Brighter.Postgres/Extensions/FluentBrighterExtensions.cs b/src/Fluent.Brighter.Postgres/Extensions/FluentBrighterExtensions.cs index 6f40060..ebd0f2d 100644 --- a/src/Fluent.Brighter.Postgres/Extensions/FluentBrighterExtensions.cs +++ b/src/Fluent.Brighter.Postgres/Extensions/FluentBrighterExtensions.cs @@ -4,8 +4,21 @@ namespace Fluent.Brighter; +/// +/// Provides extension methods for to configure PostgreSQL integration. +/// These extensions enable easy setup of PostgreSQL-based messaging, outbox patterns, inbox patterns, +/// distributed locking, and message subscriptions/publications. +/// public static class FluentBrighterExtensions { + /// + /// Configures Fluent Brighter to use PostgreSQL for messaging infrastructure. + /// This method provides a fluent API for setting up all PostgreSQL-related features including + /// message queues, outbox/inbox patterns, distributed locking, and subscriptions/publications. + /// + /// The instance to configure. + /// An action that configures the with PostgreSQL-specific settings. + /// The instance for method chaining. public static FluentBrighterBuilder UsingPostgres(this FluentBrighterBuilder builder, Action configure) { diff --git a/src/Fluent.Brighter.Postgres/Extensions/PostgresInboxBuilderExtensions.cs b/src/Fluent.Brighter.Postgres/Extensions/PostgresInboxBuilderExtensions.cs index 2d174aa..83642ae 100644 --- a/src/Fluent.Brighter.Postgres/Extensions/PostgresInboxBuilderExtensions.cs +++ b/src/Fluent.Brighter.Postgres/Extensions/PostgresInboxBuilderExtensions.cs @@ -4,8 +4,20 @@ namespace Fluent.Brighter; +/// +/// Provides extension methods for to simplify configuration. +/// These extensions enable fluent configuration of PostgreSQL inbox settings using builder patterns. +/// public static class PostgresInboxBuilderExtensions { + /// + /// Sets the database configuration for the PostgreSQL inbox using a fluent configuration builder. + /// This extension method creates a , applies the provided configuration, + /// and sets the resulting configuration on the inbox builder. + /// + /// The instance to configure. + /// An action that configures the with connection details and settings. + /// The instance for method chaining. public static PostgresInboxBuilder SetConfiguration(this PostgresInboxBuilder builder, Action configure) { diff --git a/src/Fluent.Brighter.Postgres/Extensions/PostgresMessageProducerFactoryBuilderExtensions.cs b/src/Fluent.Brighter.Postgres/Extensions/PostgresMessageProducerFactoryBuilderExtensions.cs index 0b4dc42..cd5fcad 100644 --- a/src/Fluent.Brighter.Postgres/Extensions/PostgresMessageProducerFactoryBuilderExtensions.cs +++ b/src/Fluent.Brighter.Postgres/Extensions/PostgresMessageProducerFactoryBuilderExtensions.cs @@ -7,14 +7,35 @@ namespace Fluent.Brighter; +/// +/// Provides extension methods for to simplify configuration. +/// These extensions enable fluent configuration of PostgreSQL message producer factories, including +/// connection settings and publication mappings. +/// public static class PostgresMessageProducerFactoryBuilderExtensions { #region SetConnection + /// + /// Sets the PostgreSQL messaging gateway connection using a pre-configured database configuration. + /// This method creates a from the provided configuration + /// and sets it on the builder. + /// + /// The instance to configure. + /// The pre-configured relational database configuration containing connection details. + /// The instance for method chaining. public static PostgresMessageProducerFactoryBuilder SetConnection( this PostgresMessageProducerFactoryBuilder builder, RelationalDatabaseConfiguration configuration) => builder.SetConnection(new PostgresMessagingGatewayConnection(configuration)); + /// + /// Sets the PostgreSQL messaging gateway connection using a fluent configuration builder. + /// This extension method creates a , applies the provided configuration, + /// and creates a from the result. + /// + /// The instance to configure. + /// An action that configures the with connection details and settings. + /// The instance for method chaining. public static PostgresMessageProducerFactoryBuilder SetConnection( this PostgresMessageProducerFactoryBuilder builder, Action configure) @@ -27,6 +48,13 @@ public static PostgresMessageProducerFactoryBuilder SetConnection( #region AddPublication + /// + /// Adds a PostgreSQL publication to the producer factory using a configuration builder. + /// Publications define how messages are published to PostgreSQL, including topic mappings and message metadata. + /// + /// The instance to configure. + /// An action that configures the with publication settings. + /// The instance for method chaining. public static PostgresMessageProducerFactoryBuilder AddPublication( this PostgresMessageProducerFactoryBuilder builder, Action configure) @@ -36,6 +64,15 @@ public static PostgresMessageProducerFactoryBuilder AddPublication( return builder.AddPublication(publication.Build()); } + /// + /// Adds a PostgreSQL publication for a specific request type to the producer factory. + /// This method automatically configures the publication with the specified type + /// and then applies additional configuration provided by the action. + /// + /// The type of request/message that this publication will handle. Must implement . + /// The instance to configure. + /// An action that configures the with additional publication settings. + /// The instance for method chaining. public static PostgresMessageProducerFactoryBuilder AddPublication( this PostgresMessageProducerFactoryBuilder builder, Action configure) diff --git a/src/Fluent.Brighter.Postgres/Extensions/PostgresOutboxBuilderExtensions.cs b/src/Fluent.Brighter.Postgres/Extensions/PostgresOutboxBuilderExtensions.cs index 7a45a61..9b7bbd5 100644 --- a/src/Fluent.Brighter.Postgres/Extensions/PostgresOutboxBuilderExtensions.cs +++ b/src/Fluent.Brighter.Postgres/Extensions/PostgresOutboxBuilderExtensions.cs @@ -4,8 +4,20 @@ namespace Fluent.Brighter; +/// +/// Provides extension methods for to simplify configuration. +/// These extensions enable fluent configuration of PostgreSQL outbox settings using builder patterns. +/// public static class PostgresOutboxBuilderExtensions { + /// + /// Sets the database configuration for the PostgreSQL outbox using a fluent configuration builder. + /// This extension method creates a , applies the provided configuration, + /// and sets the resulting configuration on the outbox builder. + /// + /// The instance to configure. + /// An action that configures the with connection details and settings. + /// The instance for method chaining. public static PostgresOutboxBuilder SetConfiguration(this PostgresOutboxBuilder builder, Action configure) { diff --git a/src/Fluent.Brighter.Postgres/Extensions/PostgresPublicationBuilderExtensions.cs b/src/Fluent.Brighter.Postgres/Extensions/PostgresPublicationBuilderExtensions.cs index 42a30ee..dbf5f38 100644 --- a/src/Fluent.Brighter.Postgres/Extensions/PostgresPublicationBuilderExtensions.cs +++ b/src/Fluent.Brighter.Postgres/Extensions/PostgresPublicationBuilderExtensions.cs @@ -4,24 +4,73 @@ namespace Fluent.Brighter; +/// +/// Provides extension methods for to simplify configuration with convenient helper methods. +/// These extensions provide readable, intention-revealing methods for configuring channel creation behavior and message payload formats. +/// public static class PostgresPublicationBuilderExtensions { #region MakeChannels + /// + /// Configures the publication to create PostgreSQL queues/topics if they don't exist. + /// When a publication attempts to send to a non-existent queue, it will be automatically created. + /// + /// The instance to configure. + /// The instance for method chaining. public static PostgresPublicationBuilder CreateQueueIfMissing(this PostgresPublicationBuilder builder) - => builder.SetMakeChannels(OnMissingChannel.Create); - + { + return builder.SetMakeChannels(OnMissingChannel.Create); + } + + /// + /// Configures the publication to validate that PostgreSQL queues/topics exist before publishing. + /// If a queue doesn't exist, an error will be raised rather than creating it automatically. + /// + /// The instance to configure. + /// The instance for method chaining. public static PostgresPublicationBuilder ValidIfQueueExists(this PostgresPublicationBuilder builder) - => builder.SetMakeChannels(OnMissingChannel.Validate); - + { + return builder.SetMakeChannels(OnMissingChannel.Validate); + } + + /// + /// Configures the publication to assume PostgreSQL queues/topics exist without validation. + /// No checks will be performed, and the publication will attempt to use the queue regardless. + /// This is the most performant option but requires queues to be pre-created. + /// + /// The instance to configure. + /// The instance for method chaining. public static PostgresPublicationBuilder AssumeQueueExists(this PostgresPublicationBuilder builder) - => builder.SetMakeChannels(OnMissingChannel.Assume); + { + return builder.SetMakeChannels(OnMissingChannel.Assume); + } + #endregion #region Binary Message Payload + /// + /// Enables binary message payload storage in PostgreSQL. + /// Message payloads will be stored as binary data (bytea) instead of text, which can be more efficient + /// for certain message types and reduces storage overhead for binary content. + /// + /// The instance to configure. + /// The instance for method chaining. public static PostgresPublicationBuilder EnableBinaryMessagePayload(this PostgresPublicationBuilder builder) - => builder.SetBinaryMessagePayload(true); - + { + return builder.SetBinaryMessagePayload(true); + } + + /// + /// Disables binary message payload storage in PostgreSQL. + /// Message payloads will be stored as text format instead of binary data. + /// This is useful when you need human-readable messages in the database for debugging or monitoring. + /// + /// The instance to configure. + /// The instance for method chaining. public static PostgresPublicationBuilder DisableBinaryMessagePayload(this PostgresPublicationBuilder builder) - => builder.SetBinaryMessagePayload(false); + { + return builder.SetBinaryMessagePayload(false); + } + #endregion } \ No newline at end of file diff --git a/src/Fluent.Brighter.Postgres/Extensions/PostgresSubscriptionBuilderExtensions.cs b/src/Fluent.Brighter.Postgres/Extensions/PostgresSubscriptionBuilderExtensions.cs index 2c9b8fb..5b5297f 100644 --- a/src/Fluent.Brighter.Postgres/Extensions/PostgresSubscriptionBuilderExtensions.cs +++ b/src/Fluent.Brighter.Postgres/Extensions/PostgresSubscriptionBuilderExtensions.cs @@ -4,40 +4,128 @@ namespace Fluent.Brighter; +/// +/// Provides extension methods for to simplify configuration with convenient helper methods. +/// These extensions provide readable, intention-revealing methods for configuring message pump types, channel creation behavior, +/// message payload formats, and large message support. +/// public static class PostgresSubscriptionBuilderExtensions { #region Message Pump + /// + /// Configures the subscription to use the Proactor message pump pattern. + /// The Proactor pattern uses async/await for non-blocking I/O operations, making it ideal for + /// high-throughput scenarios and when handling many concurrent operations. + /// + /// The instance to configure. + /// The instance for method chaining. public static PostgresSubscriptionBuilder UseProactor(this PostgresSubscriptionBuilder builder) - => builder.SetMessagePumpType(MessagePumpType.Proactor); - + { + return builder.SetMessagePumpType(MessagePumpType.Proactor); + } + + /// + /// Configures the subscription to use the Reactor message pump pattern. + /// The Reactor pattern uses synchronous processing, which can be simpler to reason about + /// and may be preferred for CPU-bound operations or simpler workflows. + /// + /// The instance to configure. + /// The instance for method chaining. public static PostgresSubscriptionBuilder UseReactor(this PostgresSubscriptionBuilder builder) - => builder.SetMessagePumpType(MessagePumpType.Reactor); + { + return builder.SetMessagePumpType(MessagePumpType.Reactor); + } + #endregion #region MakeChannels + /// + /// Configures the subscription to create PostgreSQL queues/topics if they don't exist. + /// When a subscription attempts to consume from a non-existent queue, it will be automatically created. + /// + /// The instance to configure. + /// The instance for method chaining. public static PostgresSubscriptionBuilder CreateQueueIfMissing(this PostgresSubscriptionBuilder builder) - => builder.SetMakeChannels(OnMissingChannel.Create); - + { + return builder.SetMakeChannels(OnMissingChannel.Create); + } + + /// + /// Configures the subscription to validate that PostgreSQL queues/topics exist before consuming. + /// If a queue doesn't exist, an error will be raised rather than creating it automatically. + /// + /// The instance to configure. + /// The instance for method chaining. public static PostgresSubscriptionBuilder ValidIfQueueExists(this PostgresSubscriptionBuilder builder) - => builder.SetMakeChannels(OnMissingChannel.Validate); - + { + return builder.SetMakeChannels(OnMissingChannel.Validate); + } + + /// + /// Configures the subscription to assume PostgreSQL queues/topics exist without validation. + /// No checks will be performed, and the subscription will attempt to consume from the queue regardless. + /// This is the most performant option but requires queues to be pre-created. + /// + /// The instance to configure. + /// The instance for method chaining. public static PostgresSubscriptionBuilder AssumeQueueExists(this PostgresSubscriptionBuilder builder) - => builder.SetMakeChannels(OnMissingChannel.Assume); + { + return builder.SetMakeChannels(OnMissingChannel.Assume); + } + #endregion #region Binary Message Payload + /// + /// Enables binary message payload storage in PostgreSQL. + /// Message payloads will be stored as binary data (bytea) instead of text, which can be more efficient + /// for certain message types and reduces storage overhead for binary content. + /// + /// The instance to configure. + /// The instance for method chaining. public static PostgresSubscriptionBuilder EnableBinaryMessagePayload(this PostgresSubscriptionBuilder builder) - => builder.SetBinaryMessagePayload(true); - + { + return builder.SetBinaryMessagePayload(true); + } + + /// + /// Disables binary message payload storage in PostgreSQL. + /// Message payloads will be stored as text format instead of binary data. + /// This is useful when you need human-readable messages in the database for debugging or monitoring. + /// + /// The instance to configure. + /// The instance for method chaining. public static PostgresSubscriptionBuilder DisableBinaryMessagePayload(this PostgresSubscriptionBuilder builder) - => builder.SetBinaryMessagePayload(false); + { + return builder.SetBinaryMessagePayload(false); + } + #endregion #region Table with large message + /// + /// Enables large message support for the PostgreSQL queue table. + /// When enabled, the table schema is optimized for storing larger message payloads that exceed normal size limits. + /// This may impact performance but allows handling of messages with substantial content. + /// + /// The instance to configure. + /// The instance for method chaining. public static PostgresSubscriptionBuilder EnableTableWithLargeMessage(this PostgresSubscriptionBuilder builder) - => builder.SetTableWithLargeMessage(true); - + { + return builder.SetTableWithLargeMessage(true); + } + + /// + /// Disables large message support for the PostgreSQL queue table. + /// The table will use a standard schema optimized for normal-sized messages. + /// This provides better performance but may not accommodate very large message payloads. + /// + /// The instance to configure. + /// The instance for method chaining. public static PostgresSubscriptionBuilder DisableTableWithLargeMessage(this PostgresSubscriptionBuilder builder) - => builder.SetTableWithLargeMessage(false); + { + return builder.SetTableWithLargeMessage(false); + } + #endregion } \ No newline at end of file diff --git a/src/Fluent.Brighter.Postgres/Extensions/ProducersExtensions.cs b/src/Fluent.Brighter.Postgres/Extensions/ProducersExtensions.cs index abe176b..1cec1b3 100644 --- a/src/Fluent.Brighter.Postgres/Extensions/ProducersExtensions.cs +++ b/src/Fluent.Brighter.Postgres/Extensions/ProducersExtensions.cs @@ -7,8 +7,19 @@ namespace Fluent.Brighter; +/// +/// Provides extension methods for to configure PostgreSQL-based message producers. +/// These extensions enable easy setup of PostgreSQL publications, outbox patterns, and distributed locking for message production. +/// public static class ProducersExtensions { + /// + /// Adds a PostgreSQL publication to the producer builder using a configuration action. + /// Publications define how messages are published to PostgreSQL, including topic mappings and message metadata. + /// + /// The instance to configure. + /// An action that configures the with publication settings. + /// The instance for method chaining. public static ProducerBuilder AddPostgresPublication(this ProducerBuilder builder, Action configure) { @@ -19,6 +30,14 @@ public static ProducerBuilder AddPostgresPublication(this ProducerBuilder builde } + /// + /// Configures the producer to use a PostgreSQL outbox pattern using a database configuration builder. + /// The outbox pattern ensures reliable message publishing by storing outgoing messages in PostgreSQL + /// as part of the same transaction as domain changes, guaranteeing eventual consistency. + /// + /// The instance to configure. + /// An action that configures the with connection details. + /// The instance for method chaining. public static ProducerBuilder UsePostgresOutbox(this ProducerBuilder builder, Action configure) { @@ -27,12 +46,28 @@ public static ProducerBuilder UsePostgresOutbox(this ProducerBuilder builder, return builder.UsePostgresOutbox(configuration.Build()); } + /// + /// Configures the producer to use a PostgreSQL outbox pattern using a pre-configured database configuration. + /// The outbox pattern ensures reliable message publishing by storing outgoing messages in PostgreSQL + /// as part of the same transaction as domain changes, guaranteeing eventual consistency. + /// + /// The instance to configure. + /// The pre-configured relational database configuration containing connection details. + /// The instance for method chaining. public static ProducerBuilder UsePostgresOutbox(this ProducerBuilder builder, RelationalDatabaseConfiguration configuration) { return builder.UsePostgresOutbox(cfg => cfg.SetConfiguration(configuration)); } + /// + /// Configures the producer to use a PostgreSQL outbox pattern using a custom outbox builder configuration. + /// This method provides the most flexibility by allowing direct configuration of the , + /// including custom connection providers, data sources, and other advanced settings. + /// + /// The instance to configure. + /// An action that configures the with outbox settings. + /// The instance for method chaining. public static ProducerBuilder UsePostgresOutbox(this ProducerBuilder builder, Action configuration) { @@ -42,9 +77,30 @@ public static ProducerBuilder UsePostgresOutbox(this ProducerBuilder builder, return builder; } + /// + /// Configures the producer to use PostgreSQL-based distributed locking using a database configuration. + /// Distributed locking ensures that only one producer instance can send messages at a time in a distributed environment, + /// preventing duplicate message publishing and ensuring consistency. + /// + /// The instance to configure. + /// The relational database configuration containing connection details. + /// The instance for method chaining. public static ProducerBuilder UsePostgresDistributedLock(this ProducerBuilder builder, IAmARelationalDatabaseConfiguration configuration) - => builder.UsePostgresDistributedLock(configuration.ConnectionString); - - public static ProducerBuilder UsePostgresDistributedLock(this ProducerBuilder builder, string connectionString) - => builder.SetDistributedLock(new PostgresLockingProvider(new PostgresLockingProviderOptions(connectionString))); + { + return builder.UsePostgresDistributedLock(configuration.ConnectionString); + } + + /// + /// Configures the producer to use PostgreSQL-based distributed locking using a connection string. + /// Distributed locking ensures that only one producer instance can send messages at a time in a distributed environment, + /// preventing duplicate message publishing and ensuring consistency. + /// + /// The instance to configure. + /// The PostgreSQL database connection string. + /// The instance for method chaining. + public static ProducerBuilder UsePostgresDistributedLock(this ProducerBuilder builder, string connectionString) + { + return builder.SetDistributedLock( + new PostgresLockingProvider(new PostgresLockingProviderOptions(connectionString))); + } } \ No newline at end of file diff --git a/src/Fluent.Brighter.Postgres/PostgresConfigurator.cs b/src/Fluent.Brighter.Postgres/PostgresConfigurator.cs index 747f0de..7f0e249 100644 --- a/src/Fluent.Brighter.Postgres/PostgresConfigurator.cs +++ b/src/Fluent.Brighter.Postgres/PostgresConfigurator.cs @@ -5,11 +5,21 @@ namespace Fluent.Brighter.Postgres; +/// +/// Provides a fluent API for configuring PostgreSQL integration with Fluent Brighter. +/// This configurator allows you to set up PostgreSQL-based messaging, outbox patterns, inbox patterns, +/// distributed locking, and message subscriptions/publications. +/// public sealed class PostgresConfigurator { private PostgresMessagingGatewayConnection? _connection; private Action _action = _ => { }; + /// + /// Sets the PostgreSQL database connection using a fluent configuration builder. + /// + /// An action that configures the relational database connection settings. + /// The current instance for method chaining. public PostgresConfigurator SetConnection(Action configuration) { var builder = new RelationalDatabaseConfigurationBuilder(); @@ -17,30 +27,59 @@ public PostgresConfigurator SetConnection(Action + /// Sets the PostgreSQL database connection using a pre-configured object. + /// + /// The relational database configuration containing connection details. + /// The current instance for method chaining. public PostgresConfigurator SetConnection(RelationalDatabaseConfiguration configuration) { _connection = new PostgresMessagingGatewayConnection(configuration); return this; } + /// + /// Enables PostgreSQL-based distributed locking for message producers. + /// This ensures that only one producer instance can send messages at a time in a distributed environment. + /// + /// The current instance for method chaining. public PostgresConfigurator UseDistributedLock() { _action += fluent => fluent.Producers(x => x.UsePostgresDistributedLock(_connection!.Configuration)); return this; } + /// + /// Enables PostgreSQL-based inbox pattern for subscriptions. + /// The inbox pattern ensures message deduplication and idempotent message processing by storing + /// information about received messages in PostgreSQL. + /// + /// The current instance for method chaining. public PostgresConfigurator UseInbox() { _action += fluent => fluent.Subscriptions(s => s.UsePostgresInbox(_connection!.Configuration)); return this; } + /// + /// Enables PostgreSQL-based outbox pattern for message producers. + /// The outbox pattern ensures reliable message publishing by storing outgoing messages in PostgreSQL + /// as part of the same transaction as domain changes, guaranteeing eventual consistency. + /// + /// The current instance for method chaining. public PostgresConfigurator UseOutbox() { _action += fluent => fluent.Producers(x => x.UsePostgresOutbox(_connection!.Configuration)); return this; } + /// + /// Configures PostgreSQL-based message publications. + /// This method allows you to define how messages are published through PostgreSQL messaging gateway, + /// including topic mappings and producer settings. + /// + /// An action that configures the PostgreSQL message producer factory. + /// The current instance for method chaining. public PostgresConfigurator UsePublications(Action configure) { _action += fluent => @@ -55,6 +94,13 @@ public PostgresConfigurator UsePublications(Action + /// Configures PostgreSQL-based message subscriptions. + /// This method allows you to define how messages are consumed from PostgreSQL messaging gateway, + /// including channel configurations and subscription mappings for different message types. + /// + /// An action that configures the PostgreSQL subscriptions using the . + /// The current instance for method chaining. public PostgresConfigurator UseSubscriptions(Action configure) { _action += fluent => @@ -76,7 +122,12 @@ public PostgresConfigurator UseSubscriptions(Action + /// Applies the configured PostgreSQL settings to the Fluent Brighter builder. + /// This method is called internally to set up all the configured PostgreSQL features. + /// + /// The Fluent Brighter builder instance to configure. + /// Thrown when no database connection has been configured via or . internal void SetFluentBrighter(FluentBrighterBuilder fluentBrighter) { if (_connection == null) diff --git a/src/Fluent.Brighter.Postgres/PostgresInboxBuilder.cs b/src/Fluent.Brighter.Postgres/PostgresInboxBuilder.cs index 0e46738..096acbe 100644 --- a/src/Fluent.Brighter.Postgres/PostgresInboxBuilder.cs +++ b/src/Fluent.Brighter.Postgres/PostgresInboxBuilder.cs @@ -3,10 +3,20 @@ namespace Fluent.Brighter.Postgres; +/// +/// Builder class for configuring and creating a PostgreSQL inbox. +/// The inbox pattern ensures message deduplication and idempotent message processing by storing +/// information about received messages in PostgreSQL. +/// public sealed class PostgresInboxBuilder { private IAmARelationalDatabaseConfiguration? _configuration; + /// + /// Sets the database configuration for the PostgreSQL inbox. + /// + /// The relational database configuration containing connection details and settings. + /// The current instance for method chaining. public PostgresInboxBuilder SetConfiguration(IAmARelationalDatabaseConfiguration configuration) { _configuration = configuration; @@ -15,12 +25,24 @@ public PostgresInboxBuilder SetConfiguration(IAmARelationalDatabaseConfiguration private IAmARelationalDbConnectionProvider? _connectionProvider; + /// + /// Sets a custom database connection provider for the PostgreSQL inbox. + /// Use this when you need to provide custom connection management logic. + /// + /// The custom connection provider implementation. + /// The current instance for method chaining. public PostgresInboxBuilder SetConnectionProvider(IAmARelationalDbConnectionProvider connectionProvider) { _connectionProvider = connectionProvider; return this; } + /// + /// Builds and returns a configured instance. + /// This method is called internally to create the inbox with the configured settings. + /// + /// A configured instance. + /// Thrown when no database configuration has been set via . internal PostgreSqlInbox Build() { if (_configuration == null) diff --git a/src/Fluent.Brighter.Postgres/PostgresMessageProducerFactoryBuilder.cs b/src/Fluent.Brighter.Postgres/PostgresMessageProducerFactoryBuilder.cs index 2f0683a..341b003 100644 --- a/src/Fluent.Brighter.Postgres/PostgresMessageProducerFactoryBuilder.cs +++ b/src/Fluent.Brighter.Postgres/PostgresMessageProducerFactoryBuilder.cs @@ -5,10 +5,19 @@ namespace Fluent.Brighter.Postgres; +/// +/// Builder class for configuring and creating a PostgreSQL message producer factory. +/// This factory is responsible for creating message producers that publish messages to PostgreSQL-based messaging gateway. +/// public sealed class PostgresMessageProducerFactoryBuilder { private PostgresMessagingGatewayConnection? _connection; + /// + /// Sets the PostgreSQL messaging gateway connection to be used by the message producers. + /// + /// The PostgreSQL messaging gateway connection containing database connection details. + /// The current instance for method chaining. public PostgresMessageProducerFactoryBuilder SetConnection(PostgresMessagingGatewayConnection connection) { _connection = connection; @@ -16,12 +25,25 @@ public PostgresMessageProducerFactoryBuilder SetConnection(PostgresMessagingGate } private readonly List _publications = []; + + /// + /// Adds a publication configuration that defines how messages are published to PostgreSQL. + /// Publications define the mapping between message types and PostgreSQL topics/tables. + /// + /// The publication configuration to add. + /// The current instance for method chaining. public PostgresMessageProducerFactoryBuilder AddPublication(PostgresPublication publication) { _publications.Add(publication); return this; } + /// + /// Builds and returns a configured instance. + /// This method is called internally to create the factory with the configured connection and publications. + /// + /// A configured instance. + /// Thrown when no connection has been configured via . internal PostgresMessageProducerFactory Build() { if (_connection == null) diff --git a/src/Fluent.Brighter.Postgres/PostgresOutboxBuilder.cs b/src/Fluent.Brighter.Postgres/PostgresOutboxBuilder.cs index 112de82..0caaa35 100644 --- a/src/Fluent.Brighter.Postgres/PostgresOutboxBuilder.cs +++ b/src/Fluent.Brighter.Postgres/PostgresOutboxBuilder.cs @@ -5,10 +5,20 @@ namespace Fluent.Brighter.Postgres; +/// +/// Builder class for configuring and creating a PostgreSQL outbox. +/// The outbox pattern ensures reliable message publishing by storing outgoing messages in PostgreSQL +/// as part of the same transaction as domain changes, guaranteeing eventual consistency. +/// public sealed class PostgresOutboxBuilder { private IAmARelationalDatabaseConfiguration? _configuration; + /// + /// Sets the database configuration for the PostgreSQL outbox. + /// + /// The relational database configuration containing connection details and settings. + /// The current instance for method chaining. public PostgresOutboxBuilder SetConfiguration(IAmARelationalDatabaseConfiguration configuration) { _configuration = configuration; @@ -17,6 +27,12 @@ public PostgresOutboxBuilder SetConfiguration(IAmARelationalDatabaseConfiguratio private IAmARelationalDbConnectionProvider? _connectionProvider; + /// + /// Sets a custom database connection provider for the PostgreSQL outbox. + /// Use this when you need to provide custom connection management logic. + /// + /// The custom connection provider implementation. + /// The current instance for method chaining. public PostgresOutboxBuilder SetConnectionProvider(IAmARelationalDbConnectionProvider connectionProvider) { _connectionProvider = connectionProvider; @@ -25,12 +41,25 @@ public PostgresOutboxBuilder SetConnectionProvider(IAmARelationalDbConnectionPro private NpgsqlDataSource? _dataSource; + /// + /// Sets an Npgsql data source for the PostgreSQL outbox. + /// This provides an alternative way to configure database connections using Npgsql's data source API. + /// + /// The Npgsql data source to use for database connections. + /// The current instance for method chaining. public PostgresOutboxBuilder SetDataSource(NpgsqlDataSource dataSource) { _dataSource = dataSource; return this; } + /// + /// Builds and returns a configured instance. + /// This method is called internally to create the outbox with the configured settings. + /// The outbox will use either the connection provider or data source, depending on which was configured. + /// + /// A configured instance. + /// Thrown when no database configuration has been set via . internal PostgreSqlOutbox Build() { if (_configuration == null) diff --git a/src/Fluent.Brighter.Postgres/PostgresPublicationBuilder.cs b/src/Fluent.Brighter.Postgres/PostgresPublicationBuilder.cs index ae2e3d8..3f2d096 100644 --- a/src/Fluent.Brighter.Postgres/PostgresPublicationBuilder.cs +++ b/src/Fluent.Brighter.Postgres/PostgresPublicationBuilder.cs @@ -6,10 +6,21 @@ namespace Fluent.Brighter.Postgres; +/// +/// Builder class for configuring and creating a PostgreSQL publication. +/// A publication defines how messages are published to PostgreSQL, including topic mappings, +/// message metadata, CloudEvents properties, and database-specific settings. +/// public sealed class PostgresPublicationBuilder { private Uri? _dataSchema; + /// + /// Sets the data schema URI for CloudEvents messages. + /// This defines the schema that describes the structure of the message data. + /// + /// The URI pointing to the data schema definition, or null if no schema is defined. + /// The current instance for method chaining. public PostgresPublicationBuilder SetDataSchema(Uri? dataSchema) { _dataSchema = dataSchema; @@ -18,6 +29,12 @@ public PostgresPublicationBuilder SetDataSchema(Uri? dataSchema) private OnMissingChannel _makeChannels = OnMissingChannel.Create; + /// + /// Sets the behavior for handling missing channels/topics in PostgreSQL. + /// Determines whether to create, validate, or assume the existence of channels. + /// + /// The behavior to apply. Default is . + /// The current instance for method chaining. public PostgresPublicationBuilder SetMakeChannels(OnMissingChannel makeChannels) { _makeChannels = makeChannels; @@ -27,6 +44,12 @@ public PostgresPublicationBuilder SetMakeChannels(OnMissingChannel makeChannels) private Type? _requestType; + /// + /// Sets the request type for the publication. + /// This defines the .NET type of the message/command/event that will be published. + /// + /// The of the request, or null if not specified. + /// The current instance for method chaining. public PostgresPublicationBuilder SetRequestType(Type? requestType) { _requestType = requestType; @@ -36,6 +59,12 @@ public PostgresPublicationBuilder SetRequestType(Type? requestType) private Uri _source = new(MessageHeader.DefaultSource); + /// + /// Sets the source URI for CloudEvents messages. + /// This identifies the context in which an event happened and is part of the CloudEvents specification. + /// + /// The URI identifying the source of the event. Default is . + /// The current instance for method chaining. public PostgresPublicationBuilder SetSource(Uri source) { _source = source; @@ -44,6 +73,12 @@ public PostgresPublicationBuilder SetSource(Uri source) private string? _subject; + /// + /// Sets the subject for CloudEvents messages. + /// This describes the subject of the event in the context of the event producer and is part of the CloudEvents specification. + /// + /// The subject of the event, or null if not specified. + /// The current instance for method chaining. public PostgresPublicationBuilder SetSubject(string? subject) { _subject = subject; @@ -52,6 +87,12 @@ public PostgresPublicationBuilder SetSubject(string? subject) private RoutingKey? _topic; + /// + /// Sets the routing key (topic/queue name) where messages will be published in PostgreSQL. + /// This determines the destination topic for outgoing messages. + /// + /// The routing key identifying the PostgreSQL topic/queue, or null if not specified. + /// The current instance for method chaining. public PostgresPublicationBuilder SetQueue(RoutingKey? topic) { _topic = topic; @@ -60,6 +101,12 @@ public PostgresPublicationBuilder SetQueue(RoutingKey? topic) private CloudEventsType _type = CloudEventsType.Empty; + /// + /// Sets the CloudEvents type for messages. + /// This describes the type of event related to the originating occurrence and is part of the CloudEvents specification. + /// + /// The to apply. Default is . + /// The current instance for method chaining. public PostgresPublicationBuilder SetType(CloudEventsType type) { _type = type; @@ -68,6 +115,12 @@ public PostgresPublicationBuilder SetType(CloudEventsType type) private IDictionary? _defaultHeaders; + /// + /// Sets default headers to be included with every published message. + /// These headers provide additional metadata that will be sent along with messages. + /// + /// A dictionary of default header key-value pairs, or null if no default headers are needed. + /// The current instance for method chaining. public PostgresPublicationBuilder SetDefaultHeaders(IDictionary? defaultHeaders) { _defaultHeaders = defaultHeaders; @@ -77,6 +130,12 @@ public PostgresPublicationBuilder SetDefaultHeaders(IDictionary? private IDictionary? _cloudEventsAdditionalProperties; + /// + /// Sets additional CloudEvents extension properties to be included with published messages. + /// CloudEvents allows custom extension attributes beyond the standard specification to provide additional context. + /// + /// A dictionary of additional CloudEvents properties, or null if no additional properties are needed. + /// The current instance for method chaining. public PostgresPublicationBuilder SetCloudEventsAdditionalProperties( IDictionary? cloudEventsAdditionalProperties) { @@ -86,6 +145,12 @@ public PostgresPublicationBuilder SetCloudEventsAdditionalProperties( private string? _replyTo; + /// + /// Sets the reply-to address for request-reply messaging patterns. + /// This specifies where response messages should be sent when implementing request-reply communication. + /// + /// The reply-to address/topic name, or null if no reply is expected. + /// The current instance for method chaining. public PostgresPublicationBuilder SetReplyTo(string? replyTo) { _replyTo = replyTo; @@ -95,6 +160,12 @@ public PostgresPublicationBuilder SetReplyTo(string? replyTo) private string? _schemaName; + /// + /// Sets the PostgreSQL database schema name where the message queue tables are located. + /// This allows you to organize queue tables in a specific database schema. + /// + /// The PostgreSQL schema name, or null to use the default schema. + /// The current instance for method chaining. public PostgresPublicationBuilder SetSchemaName(string? schemaName) { _schemaName = schemaName; @@ -103,6 +174,12 @@ public PostgresPublicationBuilder SetSchemaName(string? schemaName) private string? _queueStoreTable; + /// + /// Sets the PostgreSQL table name to use for storing messages in the queue. + /// This allows you to customize the table name where messages are persisted. + /// + /// The PostgreSQL table name for the queue store, or null to use the default table name. + /// The current instance for method chaining. public PostgresPublicationBuilder SetQueueStoreTable(string? queueStoreTable) { _queueStoreTable = queueStoreTable; @@ -111,12 +188,24 @@ public PostgresPublicationBuilder SetQueueStoreTable(string? queueStoreTable) private bool? _binaryMessagePayload; + /// + /// Sets whether to store message payloads in binary format in PostgreSQL. + /// When enabled, message payloads are stored as binary data (bytea) instead of text, which can be more efficient for certain message types. + /// + /// True to use binary format, false for text format, or null to use the default setting. + /// The current instance for method chaining. public PostgresPublicationBuilder SetBinaryMessagePayload(bool? binaryMessagePayload) { _binaryMessagePayload = binaryMessagePayload; return this; } + /// + /// Builds and returns a configured instance. + /// This method is called internally to create the publication with all the configured settings + /// including CloudEvents properties, routing information, and PostgreSQL-specific options. + /// + /// A configured instance. internal PostgresPublication Build() { return new PostgresPublication @@ -135,6 +224,5 @@ internal PostgresPublication Build() QueueStoreTable = _queueStoreTable, BinaryMessagePayload = _binaryMessagePayload }; - } } \ No newline at end of file diff --git a/src/Fluent.Brighter.Postgres/PostgresSubscriptionBuilder.cs b/src/Fluent.Brighter.Postgres/PostgresSubscriptionBuilder.cs index 7ef9dc8..4b3f314 100644 --- a/src/Fluent.Brighter.Postgres/PostgresSubscriptionBuilder.cs +++ b/src/Fluent.Brighter.Postgres/PostgresSubscriptionBuilder.cs @@ -5,10 +5,21 @@ namespace Fluent.Brighter.Postgres; +/// +/// Builder class for configuring and creating a PostgreSQL subscription. +/// A subscription defines how messages are consumed from PostgreSQL, including channel settings, +/// message processing options, retry behavior, and PostgreSQL-specific configurations. +/// public sealed class PostgresSubscriptionBuilder { private SubscriptionName? _subscriptionName; + /// + /// Sets the subscription name that uniquely identifies this subscription. + /// The subscription name is used to track and manage the subscription within the Brighter framework. + /// + /// The unique name for this subscription. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetSubscription(SubscriptionName subscriptionName) { _subscriptionName = subscriptionName; @@ -17,6 +28,14 @@ public PostgresSubscriptionBuilder SetSubscription(SubscriptionName subscription private ChannelName? _channelName; private RoutingKey? _routingKey; + + /// + /// Sets the channel name and routing key for the subscription. + /// The channel represents the PostgreSQL queue/topic from which messages will be consumed. + /// This method automatically sets the routing key to match the channel name. + /// + /// The name of the channel to subscribe to. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetQueue(ChannelName channelName) { _channelName = channelName; @@ -26,6 +45,13 @@ public PostgresSubscriptionBuilder SetQueue(ChannelName channelName) private Type? _dataType; + /// + /// Sets the data type for messages in this subscription. + /// When provided, this method will automatically configure the subscription name, channel name, + /// and routing key based on the type name if they haven't been explicitly set. + /// + /// The .NET type of the messages that will be consumed, or null if not specified. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetDataType(Type? dataType) { _dataType = dataType; @@ -54,6 +80,12 @@ public PostgresSubscriptionBuilder SetDataType(Type? dataType) private Func? _getRequestType; + /// + /// Sets a function that determines the request type dynamically based on the message content. + /// This allows for polymorphic message handling where different message types can be processed by different handlers. + /// + /// A function that takes a and returns the corresponding .NET type, or null to use the default behavior. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetGetRequestType(Func? getRequestType) { _getRequestType = getRequestType; @@ -62,6 +94,13 @@ public PostgresSubscriptionBuilder SetGetRequestType(Func? getReq private int _bufferSize = 1; + /// + /// Sets the buffer size for the message channel. + /// The buffer size determines how many messages can be queued in memory before processing, + /// allowing for better throughput in high-volume scenarios. + /// + /// The buffer size (number of messages). Default is 1. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetBufferSize(int bufferSize) { _bufferSize = bufferSize; @@ -70,6 +109,12 @@ public PostgresSubscriptionBuilder SetBufferSize(int bufferSize) private int _noOfPerformers = 1; + /// + /// Sets the number of performer threads that will process messages concurrently. + /// Multiple performers allow parallel message processing, improving throughput for I/O-bound operations. + /// + /// The number of concurrent performers. Default is 1. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetNumberOfPerformers(int noOfPerformers) { _noOfPerformers = noOfPerformers; @@ -77,6 +122,13 @@ public PostgresSubscriptionBuilder SetNumberOfPerformers(int noOfPerformers) } private TimeSpan? _timeOut; + + /// + /// Sets the timeout duration for message processing operations. + /// If a message handler takes longer than this timeout, the operation will be cancelled. + /// + /// The timeout duration, or null to use the default timeout. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetTimeout(TimeSpan? timeout) { _timeOut = timeout; @@ -84,6 +136,13 @@ public PostgresSubscriptionBuilder SetTimeout(TimeSpan? timeout) } private int _requeueCount = -1; + + /// + /// Sets the maximum number of times a failed message will be requeued for retry. + /// Messages that fail processing can be retried up to this limit before being moved to a dead letter queue or discarded. + /// + /// The maximum requeue count. Use -1 for unlimited retries. Default is -1. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetRequeueCount(int requeueCount) { _requeueCount = requeueCount; @@ -91,6 +150,13 @@ public PostgresSubscriptionBuilder SetRequeueCount(int requeueCount) } private TimeSpan? _requeueDelay; + + /// + /// Sets the delay before a failed message is requeued for retry. + /// This provides a backoff period before attempting to process the message again, which can help with transient failures. + /// + /// The requeue delay duration, or null to use the default delay. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetRequeueDelay(TimeSpan? timeout) { _requeueDelay = timeout; @@ -98,6 +164,13 @@ public PostgresSubscriptionBuilder SetRequeueDelay(TimeSpan? timeout) } private int _unacceptableMessageLimit; + + /// + /// Sets the limit for the number of unacceptable messages that can be received before the channel stops processing. + /// Unacceptable messages are those that cannot be deserialized or are malformed. This limit prevents endless processing of bad messages. + /// + /// The maximum number of unacceptable messages before stopping. Use 0 for unlimited. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetUnacceptableMessageLimit(int unacceptableMessageLimit) { _unacceptableMessageLimit = unacceptableMessageLimit ; @@ -105,6 +178,13 @@ public PostgresSubscriptionBuilder SetUnacceptableMessageLimit(int unacceptableM } private MessagePumpType _messagePumpType = MessagePumpType.Proactor; + + /// + /// Sets the message pump type that determines how messages are processed. + /// Proactor uses async/await patterns for non-blocking I/O, while Reactor uses synchronous processing. + /// + /// The to use. Default is . + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetMessagePumpType(MessagePumpType messagePumpType) { _messagePumpType = messagePumpType; @@ -113,6 +193,12 @@ public PostgresSubscriptionBuilder SetMessagePumpType(MessagePumpType messagePum private IAmAChannelFactory? _channelFactory; + /// + /// Sets a custom channel factory for creating message channels. + /// Use this when you need to provide custom channel creation logic beyond the default PostgreSQL channel factory. + /// + /// The custom channel factory implementation, or null to use the default. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetChannelFactory(IAmAChannelFactory? channelFactory) { _channelFactory = channelFactory; @@ -120,6 +206,13 @@ public PostgresSubscriptionBuilder SetChannelFactory(IAmAChannelFactory? channel } private OnMissingChannel _onMissingChannel = OnMissingChannel.Create; + + /// + /// Sets the behavior for handling missing channels/topics in PostgreSQL. + /// Determines whether to create, validate, or assume the existence of channels when they are not found. + /// + /// The behavior to apply. Default is . + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetMakeChannels(OnMissingChannel onMissingChannel) { _onMissingChannel = onMissingChannel; @@ -127,6 +220,13 @@ public PostgresSubscriptionBuilder SetMakeChannels(OnMissingChannel onMissingCha } private TimeSpan? _emptyChannelDelay; + + /// + /// Sets the delay before checking for messages again when the channel is empty. + /// This prevents tight polling loops and reduces database load when no messages are available. + /// + /// The delay duration when the channel is empty, or null to use the default delay. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetEmptyChannelDelay(TimeSpan? emptyChannelDelay) { _emptyChannelDelay = emptyChannelDelay; @@ -134,6 +234,13 @@ public PostgresSubscriptionBuilder SetEmptyChannelDelay(TimeSpan? emptyChannelDe } private TimeSpan? _channelFailureDelay; + + /// + /// Sets the delay before retrying channel operations after a failure. + /// This provides a backoff period when channel errors occur, preventing rapid retry loops that could overwhelm the system. + /// + /// The delay duration after a channel failure, or null to use the default delay. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetChannelFailureDelay(TimeSpan? channelFailureDelay) { _channelFailureDelay = channelFailureDelay; @@ -141,6 +248,13 @@ public PostgresSubscriptionBuilder SetChannelFailureDelay(TimeSpan? channelFailu } private string? _schemaName; + + /// + /// Sets the PostgreSQL database schema name where the message queue tables are located. + /// This allows you to organize queue tables in a specific database schema. + /// + /// The PostgreSQL schema name, or null to use the default schema. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetSchemaName(string? schemaName) { _schemaName = schemaName; @@ -148,6 +262,13 @@ public PostgresSubscriptionBuilder SetSchemaName(string? schemaName) } private string? _queueStoreTable; + + /// + /// Sets the PostgreSQL table name to use for storing messages in the queue. + /// This allows you to customize the table name where messages are persisted. + /// + /// The PostgreSQL table name for the queue store, or null to use the default table name. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetQueueStoreTable(string? queueStoreTable) { _queueStoreTable = queueStoreTable; @@ -155,6 +276,14 @@ public PostgresSubscriptionBuilder SetQueueStoreTable(string? queueStoreTable) } private TimeSpan? _visibleTimeout; + + /// + /// Sets the visibility timeout for messages in the queue. + /// Messages that are being processed become invisible to other consumers for this duration. + /// If processing doesn't complete within this timeout, the message becomes visible again for reprocessing. + /// + /// The visibility timeout duration, or null to use the default timeout. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetVisibleTimeout(TimeSpan? visibleTimeout) { _visibleTimeout = visibleTimeout; @@ -162,6 +291,13 @@ public PostgresSubscriptionBuilder SetVisibleTimeout(TimeSpan? visibleTimeout) } private bool _tableWithLargeMessage; + + /// + /// Sets whether the queue table should be configured to handle large messages. + /// When enabled, the table schema is optimized for storing larger message payloads that exceed normal size limits. + /// + /// True to enable large message support, false otherwise. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetTableWithLargeMessage(bool tableWithLargeMessage) { _tableWithLargeMessage = tableWithLargeMessage; @@ -169,12 +305,26 @@ public PostgresSubscriptionBuilder SetTableWithLargeMessage(bool tableWithLargeM } private bool? _binaryMessagePayload; + + /// + /// Sets whether to store message payloads in binary format in PostgreSQL. + /// When enabled, message payloads are stored as binary data (bytea) instead of text, which can be more efficient for certain message types. + /// + /// True to use binary format, false for text format, or null to use the default setting. + /// The current instance for method chaining. public PostgresSubscriptionBuilder SetBinaryMessagePayload(bool? binaryMessagePayload) { _binaryMessagePayload = binaryMessagePayload; return this; } + /// + /// Builds and returns a configured instance. + /// This method is called internally to create the subscription with all the configured settings + /// including channel configuration, message processing options, and PostgreSQL-specific settings. + /// + /// A configured instance. + /// Thrown when required configuration is missing: subscription name, channel name, or routing key. internal PostgresSubscription Build() { if (_subscriptionName == null) diff --git a/src/Fluent.Brighter.Postgres/PostgresSubscriptionConfigurator.cs b/src/Fluent.Brighter.Postgres/PostgresSubscriptionConfigurator.cs index dbdfc65..4c77b46 100644 --- a/src/Fluent.Brighter.Postgres/PostgresSubscriptionConfigurator.cs +++ b/src/Fluent.Brighter.Postgres/PostgresSubscriptionConfigurator.cs @@ -6,16 +6,38 @@ namespace Fluent.Brighter.Postgres; +/// +/// Configurator class for managing PostgreSQL message subscriptions. +/// This class provides a fluent API for adding and configuring multiple subscriptions +/// that consume messages from PostgreSQL-based messaging queues. +/// +/// The PostgreSQL channel factory used to create message channels for subscriptions. public class PostgresSubscriptionConfigurator(PostgresChannelFactory channelFactory) { + /// + /// Gets the list of configured PostgreSQL subscriptions. + /// This property is used internally to collect all subscriptions that have been added to the configurator. + /// internal List Subscriptions { get; } = []; + /// + /// Adds a pre-configured PostgreSQL subscription to the configurator. + /// + /// The instance to add. + /// The current instance for method chaining. public PostgresSubscriptionConfigurator AddSubscription(PostgresSubscription subscription) { Subscriptions.Add(subscription); return this; } + /// + /// Adds a PostgreSQL subscription using a builder configuration action. + /// This method creates a new , applies the provided configuration, + /// and automatically sets the channel factory before building the subscription. + /// + /// An action that configures the to define subscription settings. + /// The current instance for method chaining. public PostgresSubscriptionConfigurator AddSubscription(Action configure) { var builder = new PostgresSubscriptionBuilder(); @@ -24,7 +46,14 @@ public PostgresSubscriptionConfigurator AddSubscription(Action + /// Adds a PostgreSQL subscription for a specific request type using a builder configuration action. + /// This method automatically configures the subscription with the specified type + /// and then applies any additional configuration provided. + /// + /// The type of request/message that this subscription will handle. Must implement . + /// An action that configures the with additional settings. + /// The current instance for method chaining. public PostgresSubscriptionConfigurator AddSubscription( Action configure) where TRequest : class, IRequest