From 1847302dada519b84943c2db017545fa473fc091 Mon Sep 17 00:00:00 2001 From: Ian Cooper Date: Sat, 25 Oct 2025 15:42:12 +0100 Subject: [PATCH 01/12] Update Release Notes The Release Notes were AI generated and need some fixes --- release_notes.md | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/release_notes.md b/release_notes.md index f43bfeb561..371e9b2c87 100644 --- a/release_notes.md +++ b/release_notes.md @@ -111,15 +111,15 @@ services.AddBrighter() ### Polly Resilience Pipeline -**Breaking Change**: New resilience pipeline attributes replace legacy timeout policies ([PR #3677](https://github.com/BrighterCommand/Brighter/pull/3677)): +**Breaking Change**: New resilience pipeline attributes can replace legacy Polly policies and timeout policies ([PR #3677](https://github.com/BrighterCommand/Brighter/pull/3677)): ```csharp // V9 - Deprecated -[TimeoutPolicy(milliseconds: 5000)] +[TimeoutPolicy(milliseconds: 5000, step: 1)] public override MyResult Handle(MyCommand command) { } // V10 - New approach -[UseResiliencePipeline("MyPipeline")] +[UseResiliencePipeline(policy: "MyPipeline"), step: 1] public override MyResult Handle(MyCommand command) { } ``` @@ -128,19 +128,6 @@ The `TimeoutPolicyAttribute` is now marked as obsolete. The new approach provide - **CancellationToken Integration**: Proper cancellation token flow from resilience pipelines ([PR #3698](https://github.com/BrighterCommand/Brighter/pull/3698)) - **Enhanced Context**: Request context integration with Polly's resilience context -Configure resilience pipelines in your DI container: - -```csharp -services.AddResilienceEnrichment(); -services.Configure(options => -{ - options.Pipelines.Add("MyPipeline", builder => builder - .AddTimeout(TimeSpan.FromSeconds(5)) - .AddRetry(new RetryStrategyOptions()) - .AddCircuitBreaker(new CircuitBreakerStrategyOptions())); -}); -``` - ### Default Message Mappers **Important Clarification**: An explicit message mapper isn't always required for every `IRequest`. Brighter provides default mappers that can handle most common scenarios: @@ -172,6 +159,7 @@ public class MyCustomMapper : IAmAMessageMapper - **Partition Key**: Set message partition keys dynamically (see [PR #3678](https://github.com/BrighterCommand/Brighter/pull/3678)) - **Custom Headers**: Add headers via request context +- **Originating Message**: Where you are handling a message received from a queue or stream (ServiceActivator) then the `OriginalMessage` (in Brighter's message format) is now available on the `RequestContext` - **Resilience Context**: Integration with Polly Resilience Pipeline ```csharp @@ -229,9 +217,9 @@ var subscription = new RmqSubscription( - **Outbox Improvements**: Enhanced outbox pattern with better URI handling and code consolidation ([PR #3659](https://github.com/BrighterCommand/Brighter/pull/3659)) - **RocketMQ Fixes**: Various improvements to RocketMQ transport ([PR #3696](https://github.com/BrighterCommand/Brighter/pull/3696)) -### Circuit Breaking +### Outbox Sweeper Circuit Breaking -Topic-level circuit breaking has been added to prevent cascade failures: +Topic-level circuit breaking has been added to the Outbox Sweeper to prevent cascade failures: - **Failure Tracking**: Automatic tracking of dispatch failures per topic - **Configurable Thresholds**: Set failure thresholds and cooldown periods @@ -330,10 +318,11 @@ For users upgrading from V9 to V10: - Address nullable warnings in your handlers and commands 3. **Update Builder Calls**: - - Replace messaging builder methods with `AddProducers()`/`AddConsumers()` + - Replace messaging builder methods with `AddProducers()`/`AddConsumers()`. These names should be simpler than the older names to understand -4. **Migrate Timeout Policies**: - - Replace `[TimeoutPolicy]` with `[UseResiliencePipeline]` and Polly configuration +4. **[Optional] Migrate Policies to Polly Resilience policies**: + - Replace `[TimeoutPolicy]` with `[UseResiliencePipeline]` and Polly configuration ([TimeoutPolicy is deprecated in V10 and will be removed in V11] + - Replace `[UsePolicy]with `[UseResiliencePipeline]` and convert Polly Policies to Strategies via a Resilience Pipeline, see [Polly: Migration guide from v7 to v8](https://www.pollydocs.org/migration-v8.html) 5. **Message ID Changes**: - Message and Correlation IDs are now strings (defaulting to GUID strings) @@ -341,10 +330,7 @@ For users upgrading from V9 to V10: 6. **Generic Message Pumps**: - Remove generic type parameters if directly instantiating message pumps -7. **Test Framework Changes**: - - Replace Fluent Assertions with xUnit assertions in your test projects - -8. **Default Message Mappers**: +7. **Default Message Mappers**: - Review your message mappers - many can now be removed in favor of default implementations ### Database Schema Updates From a7cf83422cc8a6e9239790d98ea3ec629fa5b31b Mon Sep 17 00:00:00 2001 From: Ian Cooper Date: Sat, 25 Oct 2025 19:26:55 +0200 Subject: [PATCH 02/12] chore: fix linting errors in readme.md --- README.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index af4caeeeb3..008748042a 100644 --- a/README.md +++ b/README.md @@ -9,30 +9,28 @@ | Keywords |task queue, job queue, asynchronous, async, rabbitmq, amqp, sqs, sns, kafka, redis, c#, command, command dispatcher, command processor, queue, distributed | ## What Scenarios Can You Use Brighter in? + * When implementing a clean architecture (ports & adapters), one question is how to implement the interactor or port layer (sometimes called a mediator). + * A common solution is to use the Command pattern to implement the Interactor (port) or a pattern derived from that. + * Brighter provides an implementation the Interactor (port) using the Command Dispatcher pattern. + * You can write a command, that is then dispatched to a handler that you write. + * Alternatively you can write an event, that is dispatched to zero or more handlers that you write. + * Brighter also supports the Command Processor pattern, so that you can add middleware between the sender and handler. + * Handlers are tagged via attributes to include middleware in thier pipeline. + * Out-of-the-box middleware is provided for logging and Polly (retry, and circuit breaker). - * A common solution is to use the Command pattern to implement the Interactor (port) or a pattern derived from that. - * Brighter provides an implementation the Interactor (port) using the Command Dispatcher pattern. - * You can write a command, that is then dispatched to a handler that you write. - * Alternatively you can write an event, that is dispatched to zero or more handlers that you write. - * Brighter also supports the Command Processor pattern, so that you can add middleware between the sender and handler. - * Handlers are tagged via attributes to include middleware in thier pipeline. - * Out-of-the-box middleware is provided for logging and Polly (retry, and circuit breaker). - * When integrating two microservices using messaging, one question is how to abstract from the developer the code that sends and receives messages in favor of writing domain code. - - * A common solution is a message pump that: gets a message, translates a message, and dispatches it to user code. - * Brighter provides a service activator that implements a message pump. - * The message pump dispatches to user code via Brighter's Command Dispatcher/Processor. - * This hides the complexity of a message pump; developers need only write a handler that subscribes to a message - * This hides the complexity of messaging from developers who just write commands/events and handlers. - * Developers can take full advantage of Brighter's middleware pipeline when processing messages - * Brighter can be configured for a variety of transports including RabbitMQ, and SNS+SQS. + * A common solution is a message pump that: gets a message, translates a message, and dispatches it to user code. + * Brighter provides a service activator that implements a message pump. + * The message pump dispatches to user code via Brighter's Command Dispatcher/Processor. + * This hides the complexity of a message pump; developers need only write a handler that subscribes to a message + * This hides the complexity of messaging from developers who just write commands/events and handlers. + * Developers can take full advantage of Brighter's middleware pipeline when processing messages + * Brighter can be configured for a variety of transports including RabbitMQ, and SNS+SQS. - ## Documentation -* More detailed documentation on the project can be found on the GitBook pages for the project here: [Paramore](https://brightercommand.gitbook.io/paramore-brighter-documentation/) +* More detailed documentation on the project can be found on the GitBook pages for the project here: [Paramore](https://brightercommand.gitbook.io/paramore-brighter-documentation/) ## What are the different branches? @@ -43,11 +41,12 @@ | [Other] | A branch for any work that is not ready to go into master (for example would break CI) or is experimental i.e. we don't know if we intend to ever ship, we are just trying out ideas. | ## Using Docker Compose to test ## + We provide a Docker Compose file to allow you to run the test suite, without having to install the pre-requisites, such as brokers or databases locally. To run it, you will need to scale the redis sentinel to at least 3 nodes, and use at least two redis slaves. For example: -``` +```bash docker-compose up -d --build --scale redis-slave=2 --scale redis-sentinel=3 ``` @@ -56,6 +55,7 @@ The goal is to allow you to begin working with Brighter as easily as possible fo Note that if you have locally installed versions of these services you will either need to stop them, or edit a local version of the docker compose file. ## How do I get the NuGet packages for the latest build? + We release the build artefacts (NuGet packages) to [NuGet](http://nuget.org) on a regular basis and we update the release notes on those drops. We also tag the master code line. If you want to take the packages that represent master at any point you can download the packages for the latest good build from [GitHub Packages](https://nuget.pkg.github.com/). From a58c62b35a4ca8955e12ea4896ad01d82797828c Mon Sep 17 00:00:00 2001 From: Ian Cooper Date: Sat, 25 Oct 2025 19:58:08 +0200 Subject: [PATCH 03/12] chore: update release notes, too much AI slop --- release_notes.md | 715 ++++++++++++++++++++++++----------------------- 1 file changed, 372 insertions(+), 343 deletions(-) diff --git a/release_notes.md b/release_notes.md index 371e9b2c87..f8102092d8 100644 --- a/release_notes.md +++ b/release_notes.md @@ -1,21 +1,129 @@ -# Release Notes # -NuGet packages for the last good build on master are available via [AppVeyor](https://ci.appveyor.com/project/BrighterCommand/paramore-brighter) (see Artifacts) or the nuget feed is [https://ci.appveyor.com/nuget/paramore-brighter-m289d49fraww](https://ci.appveyor.com/nuget/paramore-brighter-m289d49fraww). The simplest way to work with this is to use the Nuget Feed, which is every successful build, So +# Release Notes + +NuGet packages for the last good build on master are available via [AppVeyor](https://ci.appveyor.com/project/BrighterCommand/paramore-brighter) (see Artifacts) or the nuget feed is [https://ci.appveyor.com/nuget/paramore-brighter-m289d49fraww](https://ci.appveyor.com/nuget/paramore-brighter-m289d49fraww). The simplest way to work with this is to use the Nuget Feed, which is every successful build, So When we push a collection of functionality it is available via [nuget.org](http://www.nuget.org) and symbol files are published to [symbolsource.org](http://www.symbolsource.org) This section lists features in master, available by [AppVeyor](https://ci.appveyor.com/project/BrighterCommand/paramore-brighter), but not yet deployed to [nuget.org](http://www.nuget.org). -## Master ## +## Master + +## Release 10.0.0 + +With V10 we have made a number of significant changes to Brighter. There are breaking changes that you will need to be aware of. However, most of the changes required are straightforward to make. A summary of the most important changes: + +* Cloud Events: We now have full support Cloud Events headers; you can set values in your Publication and have them reflected on messages. +* Open Telemetry: We now support the OpenTelemetry Semantic Conventions for Messaging. This will mean that you have different traces to V9, where the OTel conventions were Brighter's own. +* Default Message Mappers: There is no need to provide a mapper if your goal is to serialize your body as JSON. You can use a default mapper. You can create your own default mapper for other formats. You only need explicit mappers for complex transform pipelines. +* Dynamic Message Deserialization: Previously we required that you used a DataType Channel (one type per channel). Whilst we recommend this, and it remains the default you can now provide a callback to determine the message type from the message itself, such as via the Cloud Events type, before deserializing. +* Agreement Dispatcher: We now support a callback for determining the handler to dispatch a Command or Event to. Previously we matched request and handler based on the request type. Whilst this is still a default, you can now add a callback to dynamically determine the handler from the request and the request context. +* Request Context Improvements: You can now inject the RequestContext more easily into a pipeline. The RequestContext now supports the `OriginatingMessage` for subscriptions to queues or streams. +* Reactor and Proactor: We have made considerable under-the-hood improvements synchronous and asynchronous message pumps in your consumer. The asynchronous pipeline is now end-to-end. +* Scheduled Requests/Messaging: We now support integration with schedulers, like Quartz.NET, Hangfire, or AWS Scheduler. This can be used with requests or messages. We use this support internally, if available, to allow "Requeue with Delay" where the messaging protocol does not natively support it. +* Nullability: We have enabled nullable reference types. +* Simplified configuration: We have tried to make configuration simpler, including renaming obscure methods. This needs more work in future releases. + +### Cloud Events Support + +Full Cloud Events specification support has been added across all transports: + +* **Publication**: Support for Cloud Events on the Publication with configurable additional properties +* **Message Mapper**: The Publication is passed into the message mapper, allowing you to read CloudEvents properties +* **Default Mappers**: The default `JsonMessageMapper` writes `binary` Cloud Event headers, and the default `CloudEventJsonMessageMapper` writes `structured` Cloud Events Headers. +* **Transport Integration**: We support writing and reading CloudEvents headers across are supported messaging protocols. +* **Message Routing**: Use Cloud Events type for message deserialization (see below). + +### OpenTelemetry Integration + +Comprehensive OpenTelemetry support has been added throughout Brighter. We support the [OpenTelemetry Semantic Conventions](https://opentelemetry.io/docs/concepts/semantic-conventions/): + +* **Span Attributes**: OpenTelemetry across all Brighter request handler pipelines. +* **Transport Tracing**: Automatic trace propagation across message boundaries, with support for W3C TraceContext. +* **Outbox Tracing**: Distributed tracing for all outbox implementations. +* **Inbox Tracing**: OpenTelemetry support for all inbox implementations. +* **Claim Check Tracing**: Tracing support for claim check pattern and luggage stores. +* **Instrumentation Control**: Configurable instrumentation options across all tracer operations. + +OpenTelemetry integration enables end-to-end distributed tracing across message boundaries, making it easier to diagnose performance issues and understand message flow in distributed systems. + +### Default Message Mappers + +We no longer require that you implement `IAmAMessageMapper` for each Producer and Consumer message pipeline. + +* **Built-in Fallback**: Brighter will attempt to use appropriate default mappers when no explicit mapper is registered +* **JsonMapper**: Automatically handles JSON serialization/deserialization for messages with `binary` CloudEvents support +* **CloudEventsMapper**: Automatically handles JSON serialization/deserialization for messages with `structured` CloudEvents support + +You only need to create custom message mappers when you require explicit transforms or have specific serialization requirements. The default mappers can also serve as templates for custom implementations. + +```csharp + services.AddBrighter(options => + { + ... + }) + .AddProducers((configure) => + { + ... + } + //This is the default mapper type, so you can omit it, but we are explicit for this note to show how to register your own default + .AutoFromAssemblies([typeof(TaskCreated).Assembly], defaultMessageMapper: typeof(JsonMessageMapper<>), asyncDefaultMessageMapper: typeof(JsonMessageMapper<>)); +``` + +### Dynamic Message Deserialization + +Brighter now supports multiple message types on the same channel through dynamic request type resolution. This enables content-based deserialization where the message type is determined at runtime metadata rather than compile-time generic parameters. We still support the older DataType channel approach. As routing to a handler is based on type, this will decide the handler that receives this message (although see also Agreement Dispatcher). + +```csharp +new KafkaSubscription( + new SubscriptionName("paramore.example.taskstate"), + channelName: new ChannelName("task.state"), + routingKey:new RoutingKey("task.update"), + getRequestType: message => message switch + { + var m when m.Header.Type == new CloudEventsType("io.goparamore.task.created") => typeof(TaskCreated), + var m when m.Header.Type == new CloudEventsType("io.goparamore.task.updated") => typeof(TaskUpdated), + _ => throw new ArgumentException($"No type mapping found for message with type {message.Header.Type}", nameof(message)), + }, + groupId: "kafka-TaskReceiverConsole-Sample", + timeOut: TimeSpan.FromMilliseconds(100), + offsetDefault: AutoOffsetReset.Earliest, + commitBatchSize: 5, + sweepUncommittedOffsetsInterval: TimeSpan.FromMilliseconds(10000), + messagePumpType: MessagePumpType.Reactor) +``` + +### Agreement Dispatcher + +Brighter now allows you to determine the handler that will be used for a given request dynamically. Whilst we still support the old 1-2-1 mapping, this method can be used for an [Agreement Dispatcher](https://martinfowler.com/eaaDev/AgreementDispatcher.html) where we determine the handler type at runtime not build time. + +Note that we do not support auto registration of routes using `AutoFromAssemblies`, you must explicitly add them to the registry. You MUST provide both the mapping function for the agreement dispatcher and a list of possible handler types. + +```csharp +registry.RegisterAsync(((request, context) => +{ + var myCommand = request as MyCommand; + if (myCommand?.Value == "first") + return [typeof(MyImplicitHandlerAsync)]; + + return [typeof(MyCommandHandlerAsync)]; +}), + [typeof(MyImplicitHandlerAsync), typeof(MyCommandHandlerAsync)] +); +``` -## Release 10.0.0 ## +### Request Context Improvements + +The CommandProcessor now lets you set the `RequestContext` explicitly when calling `Send`, `Publish`, `DepositPost` etc. This allows you to set properties of the `RequestContext` for transmission to the `RequestHandler` instead of having a new context created by the `RequestContextFactory` for that pipeline. + +For consumers, we now add a property to the `RequestContext` that provides the `OriginatingMessage` which allows you to examine properties of the message that was received. ### Proactor and Reactor We have made significant changes to Brighter's concurrency models. We now use terminology that derives from the Reactor and Proactor patterns, replacing the previous "blocking" and "non-blocking" terminology with clearer semantic meaning. -- **Reactor Model**: Uses blocking I/O for optimal performance in single-threaded scenarios -- **Proactor Model**: Uses non-blocking I/O for improved throughput when sharing resources across multiple threads +* **Reactor Model**: Uses blocking I/O for optimal performance in single-threaded scenarios +* **Proactor Model**: Uses non-blocking I/O for improved throughput when sharing resources across multiple threads We now have a complete async pipeline for the Proactor and a complete sync pipeline for the Reactor, whereas previously only dispatch was async in the Proactor pipeline. Our synchronization context has been updated to use Stephen Cleary's AsyncEx approach instead of Stephen Toub's original article, providing better error handling and more reliable continuation management. @@ -29,89 +137,64 @@ var subscription = new Subscription(typeof(MyHandler), isAsync: true); var subscription = new Subscription(typeof(MyHandler), messagePumpType: MessagePumpType.Proactor); ``` -### Dynamic Request Types and Cloud Events +### Scheduled Requests/Messaging -Brighter now supports multiple message types on the same channel through dynamic request type resolution. This enables content-based routing where the message type is determined at runtime from Cloud Events metadata rather than compile-time generic parameters. - -**Breaking Change**: Message pump generic parameters have been removed. The message type is now determined at runtime using a `Func` strategy: +The CommandProcessor now supports using a scheduler to delay sending, publishing or posting messages. We support a range of schedulers, such as Quartz.NET, Hangfire and AWS Scheduler. ```csharp -// V9 -var pump = new Proactor(subscription, channel); -// V10 -var pump = new Proactor(subscription, channel); -// Type determined via Cloud Events or subscription strategy + _commandProcessor.Send(_timeProvider.GetUtcNow().AddSeconds(10), _myCommand); + ``` -### Cloud Events Support +```csharp +var schedulerFactory = SchedulerBuilder.Create(new NameValueCollection()) + .UseDefaultThreadPool(x => x.MaxConcurrency = 5) + .UseJobFactory() + .Build(); -Full Cloud Events specification support has been added across all transports: +var scheduler = schedulerFactory.GetScheduler().GetAwaiter().GetResult(); +scheduler.Start().GetAwaiter().GetResult(); -- **JSON Format**: Support for Cloud Events in JSON format with configurable additional properties -- **Transport Integration**: Native Cloud Events support in Kafka, AWS SNS/SQS, RabbitMQ, and MQTT -- **Message Routing**: Use Cloud Events type for message routing and handler dispatch +_scheduler = new QuartzSchedulerFactory(scheduler); -```csharp -// Configure Cloud Events -var publication = new Publication -{ - CloudEventsFormat = CloudEventsFormat.Json, - CloudEventsAdditionalProperties = new Dictionary - { - ["extension"] = "value" - } -}; ``` -### OpenTelemetry Integration +### InMemory Options -Comprehensive OpenTelemetry support has been added throughout Brighter: +Brighter has a range of in-memory types that can replace key dependencies such as producers, consumers, schedulers, outboxes and inboxes. Whilst we do not recommend this for production usage, they are robust and can be used for local development and testing. -- **Transport Tracing**: Automatic trace propagation across message boundaries with W3C TraceContext ([PR #3605](https://github.com/BrighterCommand/Brighter/pull/3605)) -- **Outbox Tracing**: Distributed tracing for all outbox implementations ([PR #3557](https://github.com/BrighterCommand/Brighter/pull/3557)) -- **Inbox Tracing**: OpenTelemetry support for all inbox implementations ([PR #3576](https://github.com/BrighterCommand/Brighter/pull/3576)) -- **Claim Check Tracing**: Tracing support for claim check pattern and luggage stores ([PR #3614](https://github.com/BrighterCommand/Brighter/pull/3614)) -- **Span Attributes**: Rich semantic attributes following OpenTelemetry conventions -- **Instrumentation Control**: Configurable instrumentation options across all tracer operations ([PR #3620](https://github.com/BrighterCommand/Brighter/pull/3620)) +```csharp +UseScheduler(new InMemorySchedulerFactory()) -OpenTelemetry integration enables end-to-end distributed tracing across message boundaries, making it easier to diagnose performance issues and understand message flow in distributed systems. +``` ### Nullable Reference Types **Breaking Change**: Nullable reference types are now enabled across all projects. You may need to update your code to handle nullable warnings: -```csharp -// Ensure proper null handling -public class MyHandler : RequestHandler -{ - public override MyCommand Handle(MyCommand command) - { - // compiler will now warn about potential null references - return command ?? throw new ArgumentNullException(nameof(command)); - } -} -``` -### Builder API Changes +### Simplified configuration -**Breaking Change**: Builder methods have been renamed for clarity: +**Breaking Change**: Builder methods have been renamed for clarity. We used names that historically had value, but are no longer meaningful to most users of Brighter, so we have reverted to a simpler naming convention: ```csharp // V9 services.AddBrighter() - .UseMessaging() - .UseRmqTransport(); + .UseExternalBus(...) + .AddServiceActivator(...); // V10 services.AddBrighter() - .AddProducers() - .AddConsumers(); + .AddProducers(...) + .AddConsumers(...); ``` +**Connection Provider Registration**: Improved registration of connection and transaction provider interfaces + ### Polly Resilience Pipeline -**Breaking Change**: New resilience pipeline attributes can replace legacy Polly policies and timeout policies ([PR #3677](https://github.com/BrighterCommand/Brighter/pull/3677)): +**Breaking Change**: New resilience pipeline attributes replace legacy timeout policies ([PR #3677](https://github.com/BrighterCommand/Brighter/pull/3677)): ```csharp // V9 - Deprecated @@ -123,44 +206,21 @@ public override MyResult Handle(MyCommand command) { } public override MyResult Handle(MyCommand command) { } ``` -The `TimeoutPolicyAttribute` is now marked as obsolete. The new approach provides: -- **Full Polly v8 Support**: Access to all Polly resilience strategies -- **CancellationToken Integration**: Proper cancellation token flow from resilience pipelines ([PR #3698](https://github.com/BrighterCommand/Brighter/pull/3698)) -- **Enhanced Context**: Request context integration with Polly's resilience context +The `TimeoutPolicyAttribute` is now marked as obsolete. -### Default Message Mappers - -**Important Clarification**: An explicit message mapper isn't always required for every `IRequest`. Brighter provides default mappers that can handle most common scenarios: +The new approach provides: -- **JsonMapper**: Automatically handles JSON serialization/deserialization for requests and events -- **CloudEventsMapper**: Handles Cloud Events format messages -- **Built-in Fallbacks**: Brighter will attempt to use appropriate default mappers when no explicit mapper is registered - -You only need to create custom message mappers when you require explicit transforms or have specific serialization requirements. The default mappers can also serve as templates for custom implementations. - -```csharp -// No explicit mapper needed - will use JsonMapper by default -public class MyCommand : Command -{ - public string Name { get; set; } - public int Value { get; set; } -} - -// Only create custom mappers when you need specific transforms -public class MyCustomMapper : IAmAMessageMapper -{ - // Custom serialization logic here -} -``` +* **Full Polly v8 Support**: Access to all Polly resilience strategies +* **CancellationToken Integration**: Proper cancellation token flow from resilience pipelines ([PR #3698](https://github.com/BrighterCommand/Brighter/pull/3698)) +* **Enhanced Context**: Request context integration with Polly's resilience context ### Request Context Enhancements **Breaking Change**: The `IRequestContext` interface has been enhanced to support: -- **Partition Key**: Set message partition keys dynamically (see [PR #3678](https://github.com/BrighterCommand/Brighter/pull/3678)) -- **Custom Headers**: Add headers via request context -- **Originating Message**: Where you are handling a message received from a queue or stream (ServiceActivator) then the `OriginalMessage` (in Brighter's message format) is now available on the `RequestContext` -- **Resilience Context**: Integration with Polly Resilience Pipeline +* **Partition Key**: Set message partition keys dynamically (see [PR #3678](https://github.com/BrighterCommand/Brighter/pull/3678)) +* **Custom Headers**: Add headers via request context +* **Resilience Context**: Integration with Polly Resilience Pipeline ```csharp // Set partition key and custom headers via request context @@ -180,9 +240,9 @@ public class MyHandler : RequestHandler Complete AWS SDK v4 support has been added: -- **SNS/SQS**: Standard and FIFO queue support -- **DynamoDB**: Inbox, Outbox, and Distributed Lock implementations -- **S3**: Luggage store for claim check pattern +* **SNS/SQS**: Standard and FIFO queue support +* **DynamoDB**: Inbox, Outbox, and Distributed Lock implementations +* **S3**: Luggage store for claim check pattern You can now use the latest AWS SDK v4 while maintaining backwards compatibility with v3. @@ -191,9 +251,10 @@ You can now use the latest AWS SDK v4 while maintaining backwards compatibility **PostgreSQL Message Broker**: Added support for using PostgreSQL as a message broker ([PR #3612](https://github.com/BrighterCommand/Brighter/pull/3612)), enabling pub/sub messaging patterns directly with PostgreSQL's LISTEN/NOTIFY functionality. **RabbitMQ Enhancements**: -- **Quorum Queues**: Support for RabbitMQ quorum queues for improved consistency and availability ([PR #3638](https://github.com/BrighterCommand/Brighter/pull/3638)) -- **RabbitMQ 7.x**: Updated to support RabbitMQ client library v7 -- **Connection Stability**: Improved connection handling and error recovery ([PR #3685](https://github.com/BrighterCommand/Brighter/pull/3685)) + +* **Quorum Queues**: Support for RabbitMQ quorum queues for improved consistency and availability. +* **RabbitMQ 7.x**: We have support for the older RabbitMQ v6 to support synchronous RMQ pipelines and support for the asynchronous pipelines of RabbitMQ client library v7 +* **Connection Stability**: Improved connection handling and error recovery. ```csharp // Configure Quorum queues @@ -205,94 +266,44 @@ var subscription = new RmqSubscription( ``` **Kafka Improvements**: -- **Configuration Callback**: Enhanced configuration support through KafkaSubscription callback ([PR #3640](https://github.com/BrighterCommand/Brighter/pull/3640)) -- **Updated Defaults**: Improved default configuration values for better out-of-the-box experience ([PR #3618](https://github.com/BrighterCommand/Brighter/pull/3618)) -**AWS Improvements**: -- **SQS Publication Enhancement**: Allow setting queue attributes and channel type in SqsPublication ([PR #3666](https://github.com/BrighterCommand/Brighter/pull/3666)) -- **S3 Claim-Check**: Fixed AWS S3 claim-check implementation ([PR #3632](https://github.com/BrighterCommand/Brighter/pull/3632)) +* **Configuration Callback**: Enhanced configuration support through KafkaSubscription callback +* **Updated Defaults**: Improved default configuration values for better out-of-the-box experience -**General Transport Features**: -- **Cloud Events Unwrapping**: Fixed Cloud Events unwrapping for JSON format ([PR #3686](https://github.com/BrighterCommand/Brighter/pull/3686)) -- **Outbox Improvements**: Enhanced outbox pattern with better URI handling and code consolidation ([PR #3659](https://github.com/BrighterCommand/Brighter/pull/3659)) -- **RocketMQ Fixes**: Various improvements to RocketMQ transport ([PR #3696](https://github.com/BrighterCommand/Brighter/pull/3696)) +**AWS Improvements**: +* **SQS Publication Enhancement**: Allow publishing directly to an SQS queue without SNS +* **S3 Claim-Check**: Fixed AWS S3 claim-check implementation -### Outbox Sweeper Circuit Breaking +### Sweeper Circuit Breaking -Topic-level circuit breaking has been added to the Outbox Sweeper to prevent cascade failures: +Topic-level circuit breaking has been added to prevent cascade failures: -- **Failure Tracking**: Automatic tracking of dispatch failures per topic -- **Configurable Thresholds**: Set failure thresholds and cooldown periods -- **Automatic Recovery**: Topics automatically recover after cooldown period -- **Bulk Dispatch Support**: Circuit breaking now properly supports bulk dispatch operations ([PR #3688](https://github.com/BrighterCommand/Brighter/pull/3688)) -- **Per-Transport Integration**: Circuit breaking is integrated with MongoDB ([PR #3692](https://github.com/BrighterCommand/Brighter/pull/3692)) and other outbox implementations +* **Failure Tracking**: Automatic tracking of dispatch failures per topic +* **Configurable Thresholds**: Set failure thresholds and cooldown periods +* **Automatic Recovery**: Topics automatically recover after cooldown period +* **Bulk Dispatch Support**: Circuit breaking now properly supports bulk dispatch operations +* **Per-Transport Integration**: Circuit breaking is integrated with MongoDB The bulk dispatch implementation brings circuit breaking inline with single dispatch, allowing individual batches to be retried and providing better control over transport-specific batching behavior. -See [PR #3651](https://github.com/BrighterCommand/Brighter/pull/3651) for the core implementation and [PR #3688](https://github.com/BrighterCommand/Brighter/pull/3688) for bulk dispatch support. - -### Scheduled Messaging - -Brighter now supports scheduling messages to be sent at specific times or after delays. This feature allows you to defer message processing until a future time, enabling scenarios like delayed notifications, scheduled tasks, and time-based workflows. - -- **Time-based Scheduling**: Schedule messages for specific dates and times -- **Delay-based Scheduling**: Schedule messages to be sent after a specified delay -- **Multiple Schedulers**: Support for Quartz, AWS EventBridge Scheduler, and Azure Service Bus scheduled messages -- **Command Processor Integration**: New `SendAt` and `PublishAt` methods on the Command Processor - -```csharp -// Schedule a command to be sent at a specific time -await commandProcessor.SendAt(new MyCommand(), DateTime.UtcNow.AddHours(1)); - -// Schedule an event to be published after a delay -await commandProcessor.PublishAt(new MyEvent(), TimeSpan.FromMinutes(30)); - -// Configure with Quartz scheduler -services.AddBrighter() - .UseQuartzScheduler(options => { - options.ConnectionString = connectionString; - }); -``` - -See [PR #3487](https://github.com/BrighterCommand/Brighter/pull/3487) for more details. - -### Multi-Transport Support - -A new `CombinedChannelFactory` enables using multiple transports simultaneously: - -```csharp -var factory = new CombinedChannelFactory(); -factory.AddTransport("kafka", kafkaFactory); -factory.AddTransport("rabbitmq", rmqFactory); -``` - ### Performance Improvements -- **GUID v7**: Support for GUID v7 on .NET 9+ for better database performance ([PR #3687](https://github.com/BrighterCommand/Brighter/pull/3687)) -- **Sealed Classes**: Internal classes sealed to reduce virtual dispatch overhead ([PR #3552](https://github.com/BrighterCommand/Brighter/pull/3552)) -- **Optimized Collections**: Reduced dictionary lookups and improved collection usage ([PR #3550](https://github.com/BrighterCommand/Brighter/pull/3550)) -- **Memory Optimization**: Better memory usage in SQL data readers and stream handling ([PR #3625](https://github.com/BrighterCommand/Brighter/pull/3625)) -- **Source-Generated Logging**: Migrated to source-generated logging for superior performance and stronger typing ([PR #3579](https://github.com/BrighterCommand/Brighter/pull/3579)) -- **Reduced Allocations**: Optimized string comparisons and reduced unnecessary allocations ([PR #3555](https://github.com/BrighterCommand/Brighter/pull/3555)) +* **GUID v7**: Support for GUID v7 on .NET 9+ for better database performance +* **Sealed Classes**: Internal classes sealed to reduce virtual dispatch overhead +* **Optimized Collections**: Reduced dictionary lookups and improved collection usage +* **Memory Optimization**: Better memory usage in SQL data readers and stream handling +* **Source-Generated Logging**: Migrated to source-generated logging for superior performance and stronger typing +* **Reduced Allocations**: Optimized string comparisons and reduced unnecessary allocations GUID v7 provides better database clustering and performance characteristics compared to GUID v4, especially beneficial for high-throughput scenarios with database-backed outboxes and inboxes. -### .NET 9 Support - -Brighter now supports .NET 9 with optimizations for the latest runtime features. - ### Test Infrastructure and Developer Experience -**Breaking Change**: Fluent Assertions has been removed in favor of xUnit assertions for better maintainability and licensing compliance. - **Enhanced Testing**: -- **Colorful Test Output**: Improved test runner with colorful output and GitHub Actions logger support ([PR #3635](https://github.com/BrighterCommand/Brighter/pull/3635)) -- **Better Test Infrastructure**: Enhanced test reliability and coverage across all transport implementations -- **Connection Provider Registration**: Improved registration of connection and transaction provider interfaces ([PR #3668](https://github.com/BrighterCommand/Brighter/pull/3668)) -**Code Quality Improvements**: -- **CA1852 Warnings**: Enabled and fixed analyzer warnings for unsealed classes ([PR #3554](https://github.com/BrighterCommand/Brighter/pull/3554)) -- **RFC3339 Typo Fix**: Corrected method name typo `ToRcf3339` to `ToRfc3339` ([PR #3622](https://github.com/BrighterCommand/Brighter/pull/3622)) +* **Colorful Test Output**: Improved test runner with colorful output and GitHub Actions logger support +* **Better Test Infrastructure**: Enhanced test reliability and coverage across all transport implementations + ### Command Processor Dispatching Strategy @@ -300,38 +311,40 @@ Enhanced command processor with support for content-based routing using specific ### Additional Bug Fixes and Improvements -- **Outbox Sweeper**: Fixed NullReference exception in outbox sweeper ([PR #3683](https://github.com/BrighterCommand/Brighter/pull/3683)) -- **ASB Defer Exception**: Fixed issue where Azure Service Bus defer exception caused attempted reject then complete ([PR #3619](https://github.com/BrighterCommand/Brighter/pull/3619)) -- **Scheduler Tests**: Fixed scheduler tests for long scheduling windows with proper EntryTimeToLive configuration ([PR #3582](https://github.com/BrighterCommand/Brighter/pull/3582)) -- **Quorum Queue Tests**: Enhanced quorum queue testing to properly validate queue creation ([PR #3642](https://github.com/BrighterCommand/Brighter/pull/3642)) +* **Outbox Sweeper**: Fixed NullReference exception in outbox sweeper ([PR #3683](https://github.com/BrighterCommand/Brighter/pull/3683)) +* **ASB Defer Exception**: Fixed issue where Azure Service Bus defer exception caused attempted reject then complete ([PR #3619](https://github.com/BrighterCommand/Brighter/pull/3619)) +* **Scheduler Tests**: Fixed scheduler tests for long scheduling windows with proper EntryTimeToLive configuration ([PR #3582](https://github.com/BrighterCommand/Brighter/pull/3582)) +* **Quorum Queue Tests**: Enhanced quorum queue testing to properly validate queue creation ([PR #3642](https://github.com/BrighterCommand/Brighter/pull/3642)) ### Breaking Changes Summary For users upgrading from V9 to V10: 1. **Update Subscription Configuration**: - - Replace `isAsync/runAsync` with `messagePumpType` with options of `MessagePumpType.Proactor` or `MessagePumpType.Reactor` - - Replace `timeoutInMilliseconds` with `timeOut` which is now a `TimeSpan` type - - Replace `requeueDelayInMs` with `requeueDelay` which is now a `TimeSpan` type + * Replace `isAsync/runAsync` with `messagePumpType` with options of `MessagePumpType.Proactor` or `MessagePumpType.Reactor` + * Replace `timeoutInMilliseconds` with `timeOut` which is now a `TimeSpan` type + * Replace `requeueDelayInMs` with `requeueDelay` which is now a `TimeSpan` type 2. **Handle Nullable Reference Types**: - - Address nullable warnings in your handlers and commands + * Address nullable warnings in your handlers and commands 3. **Update Builder Calls**: - - Replace messaging builder methods with `AddProducers()`/`AddConsumers()`. These names should be simpler than the older names to understand + * Replace messaging builder methods with `AddProducers()`/`AddConsumers()` -4. **[Optional] Migrate Policies to Polly Resilience policies**: - - Replace `[TimeoutPolicy]` with `[UseResiliencePipeline]` and Polly configuration ([TimeoutPolicy is deprecated in V10 and will be removed in V11] - - Replace `[UsePolicy]with `[UseResiliencePipeline]` and convert Polly Policies to Strategies via a Resilience Pipeline, see [Polly: Migration guide from v7 to v8](https://www.pollydocs.org/migration-v8.html) +4. **Migrate Timeout Policies**: + * Replace `[TimeoutPolicy]` with `[UseResiliencePipeline]` and Polly configuration 5. **Message ID Changes**: - - Message and Correlation IDs are now strings (defaulting to GUID strings) + * Message and Correlation IDs are now strings (defaulting to GUID strings) 6. **Generic Message Pumps**: - - Remove generic type parameters if directly instantiating message pumps + * Remove generic type parameters if directly instantiating message pumps + +7. **Test Framework Changes**: + * Replace Fluent Assertions with xUnit assertions in your test projects -7. **Default Message Mappers**: - - Review your message mappers - many can now be removed in favor of default implementations +8. **Default Message Mappers**: + * Review your message mappers - many can now be removed in favor of default implementations ### Database Schema Updates @@ -359,189 +372,205 @@ For detailed migration guidance, see the [V10 Migration Guide](https://brighterc * Compression Transform now available to compress messages using Gzip (or Brotli or Deflate on .NET 6 or 7) -## Release 9.3.6 ## +## Release 9.3.6 -- Set correct partition key (kafka key) for Kafka messages -- Add default option for Header bags serialisation -- Set correct span status for Send and SendAsync @easyfy-fredrik -- Note that this version pulls v7 of System.Text.Json which has breaking changes for users of System.Text.Json, see https://devblogs.microsoft.com/dotnet/system-text-json-in-dotnet-7/#breaking-changes +* Set correct partition key (kafka key) for Kafka messages +* Add default option for Header bags serialisation +* Set correct span status for Send and SendAsync @easyfy-fredrik +* Note that this version pulls v7 of System.Text.Json which has breaking changes for users of System.Text.Json, see + +## Release 9.3.0 -## Release 9.3.0 ## - Bug with DynamoDb Outbox and the Outbox Sweeper fixed. The Sweeper required a topic argument supplied by a dictionary of args - - Required adding a Dictionary to various interfaces, which defaults to null, hence the minor version bump as these interfaces have new capabiities -- Internal change to move outstanding message box to a semaphore slim over a mutex as thread-safe. Not strictly neededm, but follows our policy of moving to semaphore slim -- Changes to the DynamoDb Outbox implementation as Outstanding Message check was not behaving as expected -- The interfaces around Outbox configuration will likely change in v10 to avoid current split and need to configure on both publication and outbox + * Required adding a Dictionary to various interfaces, which defaults to null, hence the minor version bump as these interfaces have new capabiities +* Internal change to move outstanding message box to a semaphore slim over a mutex as thread-safe. Not strictly neededm, but follows our policy of moving to semaphore slim +* Changes to the DynamoDb Outbox implementation as Outstanding Message check was not behaving as expected +* The interfaces around Outbox configuration will likely change in v10 to avoid current split and need to configure on both publication and outbox + +## Release 9.1.20 -## Release 9.1.20 ## - Bug with Kafka Consumer failing to commit offsets fixed. Caused by Monitor being used for a lock on one thread and released on another, which does not work. Replaced with SemaphoreSlim. -- Behavior of Kafka Consumer offset sweep changed. It now runs every x seconds, and not every x seconds since a flush. This will cause it to run more frequently, but it is easier to reason about. - -## Release 9.1.14 ## - - Fixed missing negation operator when checking for AWS resources - -## Release 9.1.14 ## - - Renamed MessageStore to Outbox and CommandStore to Inbox for clarity with well-known pattern names outside this team - - Impact is wide, namespaces, class names and project names, so this is a ***BREAKING CHANGE*** - - Mostly you can search and replace to fix - - Added support for a global inbox via a UseInbox configuration parameter to the Command Processor - - Will insert an Inbox in all pipelines - - Can be overriden by a NoGlobalInbox attribute for don't add to pipeline, or an alternative UseInbox attribute to vary config - - The goal here is to be clearer than our own internal names, which don't help folks who were not part of this team - - The Outbox now fills up if a producer fails to send. You can set an upper limit on your producer, which is the maximum outstanding messages that you want in the Outbox before we throw an exception. This is not the same as Outbox size limits or sweeper, which is seperate and mainly intended if you don't want the Outbox limit to fail-fast on hitting a limit but keep accumulating results - - Added caching of attributes on target handlers in the pipeline build step - - This means we don't do reflection every time we build the pipeline for a request - - We do still always call the handler factory to instantiate as we don't own handler lifetime, implementer does - - We added a method to clear the pipeline cache, particularly for testing where you want to test configuration scenarios - - Added ability to persist RabbitMQ messages - - Added subscription to blocked/unblocked RMQ channel events. A warning log is created when a channel becomes blocked and an info log is generated when the channel becomes unblocked. - - Improved the Kafka Client. It now uses the publisher/creator model to ensure that a message is in Brighter format i.e. headers as well as body; updated configuration values; generally improved reliability. This is a breaking change with previous versions of the Kafka client. - - The class BrighterMessaging now only has a default constructor and now has setters on properties. Use the initializer syntax instead - new BrighterMessage{} to avoid having redundant constructor arguments. - - Changes to how we configure transports - renaming classes and extending their functionality - - Connection is renamed to Subscription - - Added a matching Publication for producers - - Base class includes the attributes that Brighter Core (Brighter & ServiceActivator) need - - Derived classes contain transport specific details - - On SQSConnection, renamed VisibilityTimeout to LockTimeout to more generically describe its purpose seperated from GatewayConfiguration, that now has a marker interface, used to connect to the Gateway and not about how we publish or subscribe - - We now have the option to declare infastructure separately and Validate or Assume it exists, still have an option to Create which is the default - - We think it will be most useful for environments like AWS where there is a price to checking (HTTP call, and often looping through results) - - Added support for a range of parameters that we did not have before such as dead letter queues, security etc via these platform specific configuration files - - Provided a short form of the BrighterMessaging constructor, that queries object provided for async versions of interfaces - - Changed IsAsync to RunAsync on a Subscription for clarity - - Supports an async pipeline: callbacks should happen on the same thread as the handler (and the pump), avoiding thread pool threads - - Fixed issue in SQlite with SQL to mark a message as dispatched - -## Release 8.1.1399 ## - - Update nuget libs - - RabbitMQ 6.* - - Fix correlationid no been sent correctly when using SqlCommandStore - -## Release 8.1.1036 ## - - Fixes issue when a rabbitmq connection is dropped it sometimes ends up with 2 connections and then does not dispose the ghost connection. - - Fix for System.InvalidOperationException: You cannot enqueue more items than the buffer length #846 - - fix for Suppress and log BrokerUnreachableException during ResetConnection #502 - -## Release 8.0.* ## - - Added SourceLink debugging and are shipping .pdb files in the nuget package. - - Strong Name in line with Open Source guidance https://docs.microsoft.com/en-us/dotnet/standard/library-guidance/strong-naming. Where libraries we rely on are not strong named we don't strong name our code. - - Removed `IAmAPolicyRegistry` and replaced it with `IPolicyRegistry` from Polly, it is a drop in replacement but in a the Polly namespace. - - Removed our `PolicyRegistry` and now use the `PolicyRegistry` from Polly, it is a drop in replacement but in a the Polly namespace. - - Support for Feature Switches on handlers - - Switch Command Sourcing Handler to using an Exists method when checking for duplicate messages - - Rewritten AWS SQS + SNS transport - - Support for DynamoDB Message and Command Stores (Jonny Olliff-Lee @DevJonny) - - Added a Call() method to CommandProcessor to support Request-Reply - - Add a context field to the command store, to allow identification of a context, and share a table across multiple handlers. Note that this is a breaking schema change for users of the command store - - Command Sourcing handler now writes to store only once the handler has successfully completed - - Renamed InputChannelFactory to ChannelFactory as we don't have an OutputChannelFactory any more (and not for some time) - - Channel buffer now only source for message pump, populated via consumer when empty - - Consumers now return an array of messages, default size of 1 but can be up to 10 - - Switch RMQ Consumers back to basic consume to support batch delivery - - RMQ now supports batch sizes of up to 10 for consuming messages - - SNS+SQS now supports batch sizes of up to 10 for consuming messages - - Added support for the Outbox pattern via DepositPost and ClearPostBox - - Fixed https://github.com/BrighterCommand/Brighter/issues/156 to allow different exchange types to be set (was broken by support of delayed exchange) +* Behavior of Kafka Consumer offset sweep changed. It now runs every x seconds, and not every x seconds since a flush. This will cause it to run more frequently, but it is easier to reason about. + +## Release 9.1.14 + +* Fixed missing negation operator when checking for AWS resources + +## Release 9.1.14 + +* Renamed MessageStore to Outbox and CommandStore to Inbox for clarity with well-known pattern names outside this team + * Impact is wide, namespaces, class names and project names, so this is a ***BREAKING CHANGE*** + * Mostly you can search and replace to fix +* Added support for a global inbox via a UseInbox configuration parameter to the Command Processor + * Will insert an Inbox in all pipelines + * Can be overriden by a NoGlobalInbox attribute for don't add to pipeline, or an alternative UseInbox attribute to vary config +* The goal here is to be clearer than our own internal names, which don't help folks who were not part of this team +* The Outbox now fills up if a producer fails to send. You can set an upper limit on your producer, which is the maximum outstanding messages that you want in the Outbox before we throw an exception. This is not the same as Outbox size limits or sweeper, which is seperate and mainly intended if you don't want the Outbox limit to fail-fast on hitting a limit but keep accumulating results +* Added caching of attributes on target handlers in the pipeline build step + * This means we don't do reflection every time we build the pipeline for a request + * We do still always call the handler factory to instantiate as we don't own handler lifetime, implementer does + * We added a method to clear the pipeline cache, particularly for testing where you want to test configuration scenarios +* Added ability to persist RabbitMQ messages +* Added subscription to blocked/unblocked RMQ channel events. A warning log is created when a channel becomes blocked and an info log is generated when the channel becomes unblocked. +* Improved the Kafka Client. It now uses the publisher/creator model to ensure that a message is in Brighter format i.e. headers as well as body; updated configuration values; generally improved reliability. This is a breaking change with previous versions of the Kafka client. +* The class BrighterMessaging now only has a default constructor and now has setters on properties. Use the initializer syntax instead - new BrighterMessage{} to avoid having redundant constructor arguments. +* Changes to how we configure transports - renaming classes and extending their functionality + * Connection is renamed to Subscription + * Added a matching Publication for producers + * Base class includes the attributes that Brighter Core (Brighter & ServiceActivator) need + * Derived classes contain transport specific details + * On SQSConnection, renamed VisibilityTimeout to LockTimeout to more generically describe its purpose seperated from GatewayConfiguration, that now has a marker interface, used to connect to the Gateway and not about how we publish or subscribe + * We now have the option to declare infastructure separately and Validate or Assume it exists, still have an option to Create which is the default + * We think it will be most useful for environments like AWS where there is a price to checking (HTTP call, and often looping through results) + * Added support for a range of parameters that we did not have before such as dead letter queues, security etc via these platform specific configuration files +* Provided a short form of the BrighterMessaging constructor, that queries object provided for async versions of interfaces +* Changed IsAsync to RunAsync on a Subscription for clarity +* Supports an async pipeline: callbacks should happen on the same thread as the handler (and the pump), avoiding thread pool threads +* Fixed issue in SQlite with SQL to mark a message as dispatched + +## Release 8.1.1399 + +* Update nuget libs +* RabbitMQ 6.* +* Fix correlationid no been sent correctly when using SqlCommandStore + +## Release 8.1.1036 + +* Fixes issue when a rabbitmq connection is dropped it sometimes ends up with 2 connections and then does not dispose the ghost connection. +* Fix for System.InvalidOperationException: You cannot enqueue more items than the buffer length #846 +* fix for Suppress and log BrokerUnreachableException during ResetConnection #502 + +## Release 8.0.* + +* Added SourceLink debugging and are shipping .pdb files in the nuget package. +* Strong Name in line with Open Source guidance . Where libraries we rely on are not strong named we don't strong name our code. +* Removed `IAmAPolicyRegistry` and replaced it with `IPolicyRegistry` from Polly, it is a drop in replacement but in a the Polly namespace. +* Removed our `PolicyRegistry` and now use the `PolicyRegistry` from Polly, it is a drop in replacement but in a the Polly namespace. +* Support for Feature Switches on handlers +* Switch Command Sourcing Handler to using an Exists method when checking for duplicate messages +* Rewritten AWS SQS + SNS transport +* Support for DynamoDB Message and Command Stores (Jonny Olliff-Lee @DevJonny) +* Added a Call() method to CommandProcessor to support Request-Reply +* Add a context field to the command store, to allow identification of a context, and share a table across multiple handlers. Note that this is a breaking schema change for users of the command store +* Command Sourcing handler now writes to store only once the handler has successfully completed +* Renamed InputChannelFactory to ChannelFactory as we don't have an OutputChannelFactory any more (and not for some time) +* Channel buffer now only source for message pump, populated via consumer when empty +* Consumers now return an array of messages, default size of 1 but can be up to 10 +* Switch RMQ Consumers back to basic consume to support batch delivery +* RMQ now supports batch sizes of up to 10 for consuming messages +* SNS+SQS now supports batch sizes of up to 10 for consuming messages +* Added support for the Outbox pattern via DepositPost and ClearPostBox +* Fixed to allow different exchange types to be set (was broken by support of delayed exchange) - -## Release 7.4.0 ## - - Updated to signed version of Polly, works with netcore2.1. - - Fix for Sql CommandStore. - - Fixes to make flaky tests stable. +## Release 7.4.0 + +* Updated to signed version of Polly, works with netcore2.1. +* Fix for Sql CommandStore. +* Fixes to make flaky tests stable. -## Release 7.3.0 ## - - Added beta Support for a Redis transport - - Support for Binding a channel to multiple topics - - RMQ Transport: Fixed handling of socket timeout where node we are connected to (not master) partitions from cluster and is paused under the pause minority strategy. Now resets connection successfully. - - RMQ Transport: Fixed issue with OperationInterrupted exception when master node partitions and we are connected to it - - Overall improved reliability of Brighter RMQ transport when connecting to a cluster that experiences a partition - - Fixed an issue where multiple performers did not have distinct names and so could not be tracked - - RMQ changed from push rabbit consumer to just simple pull based. - -## Release 7.2.0 ## - - Support for PostgreSql Message Store (Tarun Pothulapati @Pothulapati) - - Support for MySql Message and Command Stores (Derek Comartin @dcomartin) - - Support for Kafka Messaging Gateway - Beta (Wayne Hunsley @whunsley) - - Support for MSSql Messaging Gateway - Beta (Fred Hoogduin @Red-F) - -## Release 7.1.0 ## - - Fixes issue with high CPU when failing to connect to RabbitMQ. - - Fixes missing High Availability setting, had to make changes to IAmAChannelFactory. - -## Release 7.0.137 - 7.0.143 ## - - Support for .NET Core (NETSTANDARD 1.5) +## Release 7.3.0 + +* Added beta Support for a Redis transport +* Support for Binding a channel to multiple topics +* RMQ Transport: Fixed handling of socket timeout where node we are connected to (not master) partitions from cluster and is paused under the pause minority strategy. Now resets connection successfully. +* RMQ Transport: Fixed issue with OperationInterrupted exception when master node partitions and we are connected to it +* Overall improved reliability of Brighter RMQ transport when connecting to a cluster that experiences a partition +* Fixed an issue where multiple performers did not have distinct names and so could not be tracked +* RMQ changed from push rabbit consumer to just simple pull based. + +## Release 7.2.0 + +* Support for PostgreSql Message Store (Tarun Pothulapati @Pothulapati) +* Support for MySql Message and Command Stores (Derek Comartin @dcomartin) +* Support for Kafka Messaging Gateway - Beta (Wayne Hunsley @whunsley) +* Support for MSSql Messaging Gateway - Beta (Fred Hoogduin @Red-F) + +## Release 7.1.0 + +* Fixes issue with high CPU when failing to connect to RabbitMQ. +* Fixes missing High Availability setting, had to make changes to IAmAChannelFactory. + +## Release 7.0.137 - 7.0.143 + +* Support for .NET Core (NETSTANDARD 1.5) **Breaking Changes** - - Configuration no longer supports XML based config sections. We use data structures instead, and expect you to configure mostly in code, initializing those data structures from your config system of choice yourself. We recommend following 12-Factor Apps guidelines and preferring enviroment variables for items that vary by environment over XML or JSON based configuration files. (We may consider providing config sections in Contrib again, please feedback if this is a critical issue for you. PRs welcome.) - - Dropped CommandProcessor from namespaces and folder names, to shorten, and remove semantic issue that it is not just a Command Processor - - Changed namespaces and folders to be CamelCase - - As a result, your using statements will need revision with this release - - Some namespaces i.e Paramore.Brighter.Policy changed to avoid clashes now CamelCase (has become Paramore.Brighter.Policies) +* Configuration no longer supports XML based config sections. We use data structures instead, and expect you to configure mostly in code, initializing those data structures from your config system of choice yourself. We recommend following 12-Factor Apps guidelines and preferring enviroment variables for items that vary by environment over XML or JSON based configuration files. (We may consider providing config sections in Contrib again, please feedback if this is a critical issue for you. PRs welcome.) +* Dropped CommandProcessor from namespaces and folder names, to shorten, and remove semantic issue that it is not just a Command Processor +* Changed namespaces and folders to be CamelCase +* As a result, your using statements will need revision with this release +* Some namespaces i.e Paramore.Brighter.Policy changed to avoid clashes now CamelCase (has become Paramore.Brighter.Policies) + +## Release 6.1.0 + +* Support for binary message payloads i.e. not just text/plain for JSON or XML. Current support is modelled around use of protobuf over RMQ -## Release 6.1.0 ## - - Support for binary message payloads i.e. not just text/plain for JSON or XML. Current support is modelled around use of protobuf over RMQ +## Release 6.0.28 -## Release 6.0.28 ## +Fix issue with encoding of non-string types and transmission of correlation id -Fix issue with encoding of non-string types and transmission of correlation id https://github.com/BrighterCommand/Brighter/pull/180 +## Release 6.0.6 -## Release 6.0.6 ## - Increase logging level when we stop reading from a queue that cannot be readhttps://github.com/BrighterCommand/Brighter/pull/179 -- Peformance issue caused by creation of a logger per requesthandler instance. The logger is now static, but is initialized lazily and can be overridden for TDD or legacy compatibility +* Peformance issue caused by creation of a logger per requesthandler instance. The logger is now static, but is initialized lazily and can be overridden for TDD or legacy compatibility -## Release 6.0.0 ## +## Release 6.0.0 **Breaking Changes** -- CommandProcessorBuilder no longer takes .Logger(logger) -- In the abstract RequestHandler `logger` is now `Logger` -- `RequestLogging` has moved namespace to `paramore.brighter.commandprocessor.logging.Attributes` +* CommandProcessorBuilder no longer takes .Logger(logger) +* In the abstract RequestHandler `logger` is now `Logger` +* `RequestLogging` has moved namespace to `paramore.brighter.commandprocessor.logging.Attributes` **Bug fixes**: -- Fixed issue #132: concurrent usages of the RabbitMQ messaging gateway would sometimes throw an exception -- Fixed issue #134: We no longer use async/await in the command processor. This caused issues with ASP.NET synchronization contexts, resulting in a deadlock when waiting on the thread that was also being used to run the completion. See http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html We wil revisit async when we write *Async versions of the CommandProcesor APIs suitable for using in hosts that can run async code without deadlocking their synchronization context. -- Fixed issue 110: Where we want to log we have two constuctors. A constructor that directly takes an iLog that you provide either directly or via your ioC container; a constructor that defaults that to LogProvider.GetCurrentClassLogger - - In Production code you should set up your log provider and use the constructors that do not take an ILog reference. - - In Test code you should inject the ILog using a fake logger. We don't recommend testing log output, its an implementation detail, unless its an important part of your acceptance criteria for that behaviour. - - This means that your production code should not need to take a direct dependency on Paramore's ILog implementation. - - This is a BREAKING CHANGE because we remove the ability to inject the constructor via the *Builder objects, so as to remove the temptation to do that when you should rely on the LibLog framework to wrap your current logger. +* Fixed issue #132: concurrent usages of the RabbitMQ messaging gateway would sometimes throw an exception +* Fixed issue #134: We no longer use async/await in the command processor. This caused issues with ASP.NET synchronization contexts, resulting in a deadlock when waiting on the thread that was also being used to run the completion. See We wil revisit async when we write *Async versions of the CommandProcesor APIs suitable for using in hosts that can run async code without deadlocking their synchronization context. +* Fixed issue 110: Where we want to log we have two constuctors. A constructor that directly takes an iLog that you provide either directly or via your ioC container; a constructor that defaults that to LogProvider.GetCurrentClassLogger + * In Production code you should set up your log provider and use the constructors that do not take an ILog reference. + * In Test code you should inject the ILog using a fake logger. We don't recommend testing log output, its an implementation detail, unless its an important part of your acceptance criteria for that behaviour. + * This means that your production code should not need to take a direct dependency on Paramore's ILog implementation. + * This is a BREAKING CHANGE because we remove the ability to inject the constructor via the *Builder objects, so as to remove the temptation to do that when you should rely on the LibLog framework to wrap your current logger. **Features:** -- Huge feature, Async; added support for SendAsync and PublishAsync to an IHandleRequestsAsync pipeline. -- Basic support for publishing to Azure Service Bus with `paramore.brighter.commandprocessor.messaginggateway.azureservicebus`. +* Huge feature, Async; added support for SendAsync and PublishAsync to an IHandleRequestsAsync pipeline. +* Basic support for publishing to Azure Service Bus with `paramore.brighter.commandprocessor.messaginggateway.azureservicebus`. - -## Release 5 ## +## Release 5 **Bug Fixes:** - - #100 `CommandProcessor.Post` fails with Object reference not set to an instance of an object. - - Fix RequeueMessage exhaustion to log ERROR. - - #101 Updated `Requeue` method to send a message to a specific queue as opposed to a topic. - - Added a message store write timeout and message gateway timeout on a post; perviously we wait indefinitely (bad Brighter team, no biscuit). - - Replace `Successor` write-only property with `SetSuccessor` method. - - Message Viewer, fixed startup issues. - - Removed a few unused interfaces. - - Correct exceptions namespace to actions. + +* #100 `CommandProcessor.Post` fails with Object reference not set to an instance of an object. +* Fix RequeueMessage exhaustion to log ERROR. +* #101 Updated `Requeue` method to send a message to a specific queue as opposed to a topic. +* Added a message store write timeout and message gateway timeout on a post; perviously we wait indefinitely (bad Brighter team, no biscuit). +* Replace `Successor` write-only property with `SetSuccessor` method. +* Message Viewer, fixed startup issues. +* Removed a few unused interfaces. +* Correct exceptions namespace to actions. **Features:** - - A connection can now be flagged as isDurable in the configuration. Choosing isDurable when using RMQ as the broker will create a durable channel (i.e. does not die if no one is consuming it, and thus continues to subscribe to messages that match it's topic). We think there are sufficient trade-offs with a message store that allows replay to make this setting false by default, but have configured to allow users to make this choice dependent on the characteristics of their consumers (i.e. sufficiently intermittend that messages would be lost). - - #92 Added [Event Store](https://geteventstore.com/ "Event Store") Message Store implementation - - #30 Changed RabbitMQ Messaging Gateway to support multiple performers per connection, fixing the pipeline errors from RabbitMQ Client - - Added a UseCommandSourcing attribute that stores commands to a command store. This is the Event Sourcing paradigm described by Martin Fowler in http://martinfowler.com/eaaDev/EventSourcing.html The term Command Sourcing refers to the fact that as described the pattern stores commands (instructions to change state) not events (the results of applying those commands). - - This may result in a breaking change that the Id on IRequest requires a setter to allow it to be deserialized - - Added MS SQL Command Store implementation - - Added monitoring attribute, which fires message onto control bus - - Cleaning up code so working with dnx and Portable will be easier - - Message Viewer, Add paging - - Update Code of Conduct to Contributor Covenant 1.1.0 - - Add DDL scripts to help create SQL based schemes + +* A connection can now be flagged as isDurable in the configuration. Choosing isDurable when using RMQ as the broker will create a durable channel (i.e. does not die if no one is consuming it, and thus continues to subscribe to messages that match it's topic). We think there are sufficient trade-offs with a message store that allows replay to make this setting false by default, but have configured to allow users to make this choice dependent on the characteristics of their consumers (i.e. sufficiently intermittend that messages would be lost). +* #92 Added [Event Store](https://geteventstore.com/ "Event Store") Message Store implementation +* #30 Changed RabbitMQ Messaging Gateway to support multiple performers per connection, fixing the pipeline errors from RabbitMQ Client +* Added a UseCommandSourcing attribute that stores commands to a command store. This is the Event Sourcing paradigm described by Martin Fowler in The term Command Sourcing refers to the fact that as described the pattern stores commands (instructions to change state) not events (the results of applying those commands). + * This may result in a breaking change that the Id on IRequest requires a setter to allow it to be deserialized +* Added MS SQL Command Store implementation +* Added monitoring attribute, which fires message onto control bus +* Cleaning up code so working with dnx and Portable will be easier +* Message Viewer, Add paging +* Update Code of Conduct to Contributor Covenant 1.1.0 +* Add DDL scripts to help create SQL based schemes **Remove and Depreciated:** - - Flag the method `Repost` on `IAmACommandProcessor` as obsolete, We will probably drop this in the next release. We suggest that you use the message store directly to retrieve a message and then call Post. - - Dropped support for RavenDb as a message store, we feel EventStore covers this scenario better where non-relational stores are an option - - Removed release branch. We just tag a release on master now, so this only existed to support an older version of the library that was pre the tagging strategy. Removed now as confusing to new users of the library. -## Release 4.0.215 ## +* Flag the method `Repost` on `IAmACommandProcessor` as obsolete, We will probably drop this in the next release. We suggest that you use the message store directly to retrieve a message and then call Post. +* Dropped support for RavenDb as a message store, we feel EventStore covers this scenario better where non-relational stores are an option +* Removed release branch. We just tag a release on master now, so this only existed to support an older version of the library that was pre the tagging strategy. Removed now as confusing to new users of the library. + +## Release 4.0.215 + 1. Fixed an issue where you could not have multiple UsePolicy or FallbackPolicy attributes on a single handler.# 2. We pool connections now, to prevent clients with large number of channels overwhelming servers. 3. Add concept of delayed (deferred) message sending. @@ -551,25 +580,25 @@ Fix issue with encoding of non-string types and transmission of correlation id h 7. Fixed and issues with unhandled exceptions from handlers when an event is published not been logged correctly 8. The first early version of a Message Store Viewer has been release as a zip file download -## Release 3.0.129 ## +## Release 3.0.129 + 1. We now support a Fallback method on IHandleRequests which is intended to be used for compensating or emergency action when a Handle method cannot be executed. The [FallbackPolicy] attribute supports the pipeline calling the Fallback method for you, in the event of either any exception bubbling into the handler, or a broken circuit exception bubbling into the handler. 2. Fix issue with RabbitMQ consumers running on a High Availability cluster not cancelling properly after cluster failover. -3. Fixed bug with config section duplication https://github.com/BrighterCommand/Brighter/issues/52 -4. Added functionality so after a specified number of unacceptable message (unable to read from queue or map message) a connection is shutdown, by default unacceptable message are acked and dropped. https://github.com/BrighterCommand/Brighter/issues/51 +3. Fixed bug with config section duplication +4. Added functionality so after a specified number of unacceptable message (unable to read from queue or map message) a connection is shutdown, by default unacceptable message are acked and dropped. 5. Move RequeueException to paramore.brighter.commandprocessor.exceptions (breaking change). -## Release 3 ## - +## Release 3 1. Refactored **IAmAMessagingGateway** into a **IAmAMessageConsumer** and **IAmAMessageProducer** to support differing approaches to producing and consuming messages for a particular flavour of Message-Oriented-Middleware. *These changes are a breaking binary change for users of earlier versions.* - 1. NOTE: IF YOU USE TASK QUEUES PLEASE SAVE YOUR SERVICEACTIVATORCONNECTIONS IN YOUR APP.CONFIG AS THE V2.0.1 BRIGHTER.SERVICEACTIVATOR UNINSTALL WILL DELETE THEM (FIXED FOR V3) + 1. NOTE: IF YOU USE TASK QUEUES PLEASE SAVE YOUR SERVICEACTIVATORCONNECTIONS IN YOUR APP.CONFIG AS THE V2.0.1 BRIGHTER.SERVICEACTIVATOR UNINSTALL WILL DELETE THEM (FIXED FOR V3) 2. Created an **IAmAChannel** abstraction to allow differing Application Layer dependencies for the Work Queue 2. Upgraded Packages we depend on, including RabbitMQ. *There is still an issue with our having a hard dependency on a RabbitMQ client that might vary from your RabbitMQ client version, but as a NuGet package there are few workarounds. We suggest building from source where this issue is problematic, for now.* 3. Significant stability improvements on the RabbitMQ client - 1. Fixed issues around re-connection of the client leading to lost messages. - 2. Fixed issues when explicitly closing and re-opening connections - 3. Provided support for a **RequeueException** to requeue messages that are 'out-of-time' to help with resequencing. - 1. We now dispose of channels aggressively on closure, instead of waiting for garbage collection + 1. Fixed issues around re-connection of the client leading to lost messages. + 2. Fixed issues when explicitly closing and re-opening connections + 3. Provided support for a **RequeueException** to requeue messages that are 'out-of-time' to help with resequencing. + 1. We now dispose of channels aggressively on closure, instead of waiting for garbage collection 2. Moved from [Common.Logging](https://github.com/net-commons/common-logging) to [LibLog](https://github.com/damianh/LibLog) *These changes are a breaking binary change for users of earlier versions.* 3. We now call Release for all **RequestHandler<>** derived handlers that we construct from an **IAmAHandlerFactory**, not just those that implement IDisposable. 4. Note that the RestMS server is **NOT** ready for production usage. It's primary value, as of today, is an alternative to RabbitMQ for design purposes. It is hoped to produce a stable version for use as a ControlBus in a future release. From ba2c46da5c58597317729a13d2086b83ae09ae58 Mon Sep 17 00:00:00 2001 From: Ian Cooper Date: Sat, 25 Oct 2025 20:05:08 +0200 Subject: [PATCH 04/12] chore: remove out of date AppVeyor information --- Brighter.sln.DotSettings | 2 ++ release_notes.md | 6 ------ .../WebAPI_Dapper/GreetingsWeb/Greetings.db | Bin 0 -> 36864 bytes .../WebAPI_EFCore/GreetingsWeb/Greetings.db | Bin 0 -> 36864 bytes .../SalutationAnalytics/Salutations.db | Bin 0 -> 32768 bytes 5 files changed, 2 insertions(+), 6 deletions(-) create mode 100644 Brighter.sln.DotSettings create mode 100644 samples/WebAPI/WebAPI_Dapper/GreetingsWeb/Greetings.db create mode 100644 samples/WebAPI/WebAPI_EFCore/GreetingsWeb/Greetings.db create mode 100644 samples/WebAPI/WebAPI_EFCore/SalutationAnalytics/Salutations.db diff --git a/Brighter.sln.DotSettings b/Brighter.sln.DotSettings new file mode 100644 index 0000000000..3d8771c936 --- /dev/null +++ b/Brighter.sln.DotSettings @@ -0,0 +1,2 @@ + + False \ No newline at end of file diff --git a/release_notes.md b/release_notes.md index f8102092d8..3edf4b50f3 100644 --- a/release_notes.md +++ b/release_notes.md @@ -1,11 +1,5 @@ # Release Notes -NuGet packages for the last good build on master are available via [AppVeyor](https://ci.appveyor.com/project/BrighterCommand/paramore-brighter) (see Artifacts) or the nuget feed is [https://ci.appveyor.com/nuget/paramore-brighter-m289d49fraww](https://ci.appveyor.com/nuget/paramore-brighter-m289d49fraww). The simplest way to work with this is to use the Nuget Feed, which is every successful build, So - -When we push a collection of functionality it is available via [nuget.org](http://www.nuget.org) and symbol files are published to [symbolsource.org](http://www.symbolsource.org) - -This section lists features in master, available by [AppVeyor](https://ci.appveyor.com/project/BrighterCommand/paramore-brighter), but not yet deployed to [nuget.org](http://www.nuget.org). - ## Master ## Release 10.0.0 diff --git a/samples/WebAPI/WebAPI_Dapper/GreetingsWeb/Greetings.db b/samples/WebAPI/WebAPI_Dapper/GreetingsWeb/Greetings.db new file mode 100644 index 0000000000000000000000000000000000000000..ac9b7971655658bbb3024d17be61f67f2d3bc691 GIT binary patch literal 36864 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 literal 0 HcmV?d00001 From 66d461f1fcecefa6157ac7ba9d20b446f41db3e3 Mon Sep 17 00:00:00 2001 From: Ian Cooper Date: Sat, 25 Oct 2025 20:07:08 +0200 Subject: [PATCH 05/12] chore: bold change list --- release_notes.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/release_notes.md b/release_notes.md index 3edf4b50f3..866c68b2eb 100644 --- a/release_notes.md +++ b/release_notes.md @@ -6,16 +6,16 @@ With V10 we have made a number of significant changes to Brighter. There are breaking changes that you will need to be aware of. However, most of the changes required are straightforward to make. A summary of the most important changes: -* Cloud Events: We now have full support Cloud Events headers; you can set values in your Publication and have them reflected on messages. -* Open Telemetry: We now support the OpenTelemetry Semantic Conventions for Messaging. This will mean that you have different traces to V9, where the OTel conventions were Brighter's own. -* Default Message Mappers: There is no need to provide a mapper if your goal is to serialize your body as JSON. You can use a default mapper. You can create your own default mapper for other formats. You only need explicit mappers for complex transform pipelines. -* Dynamic Message Deserialization: Previously we required that you used a DataType Channel (one type per channel). Whilst we recommend this, and it remains the default you can now provide a callback to determine the message type from the message itself, such as via the Cloud Events type, before deserializing. -* Agreement Dispatcher: We now support a callback for determining the handler to dispatch a Command or Event to. Previously we matched request and handler based on the request type. Whilst this is still a default, you can now add a callback to dynamically determine the handler from the request and the request context. -* Request Context Improvements: You can now inject the RequestContext more easily into a pipeline. The RequestContext now supports the `OriginatingMessage` for subscriptions to queues or streams. -* Reactor and Proactor: We have made considerable under-the-hood improvements synchronous and asynchronous message pumps in your consumer. The asynchronous pipeline is now end-to-end. -* Scheduled Requests/Messaging: We now support integration with schedulers, like Quartz.NET, Hangfire, or AWS Scheduler. This can be used with requests or messages. We use this support internally, if available, to allow "Requeue with Delay" where the messaging protocol does not natively support it. -* Nullability: We have enabled nullable reference types. -* Simplified configuration: We have tried to make configuration simpler, including renaming obscure methods. This needs more work in future releases. +* **Cloud Events**: We now have full support Cloud Events headers; you can set values in your Publication and have them reflected on messages. +* **Open Telemetry**: We now support the OpenTelemetry Semantic Conventions for Messaging. This will mean that you have different traces to V9, where the OTel conventions were Brighter's own. +* **Default Message Mappers**: There is no need to provide a mapper if your goal is to serialize your body as JSON. You can use a default mapper. You can create your own default mapper for other formats. You only need explicit mappers for complex transform pipelines. +* **Dynamic Message Deserialization**: Previously we required that you used a DataType Channel (one type per channel). Whilst we recommend this, and it remains the default you can now provide a callback to determine the message type from the message itself, such as via the Cloud Events type, before deserializing. +* **Agreement Dispatcher**: We now support a callback for determining the handler to dispatch a Command or Event to. Previously we matched request and handler based on the request type. Whilst this is still a default, you can now add a callback to dynamically determine the handler from the request and the request context. +* **Request Context Improvements**: You can now inject the RequestContext more easily into a pipeline. The RequestContext now supports the `OriginatingMessage` for subscriptions to queues or streams. +* **Reactor and Proactor**: We have made considerable under-the-hood improvements synchronous and asynchronous message pumps in your consumer. The asynchronous pipeline is now end-to-end. +* **Scheduled Requests/Messaging**: We now support integration with schedulers, like Quartz.NET, Hangfire, or AWS Scheduler. This can be used with requests or messages. We use this support internally, if available, to allow "Requeue with Delay" where the messaging protocol does not natively support it. +* **Nullability**: We have enabled nullable reference types. +* **Simplified Configuration**: We have tried to make configuration simpler, including renaming obscure methods. This needs more work in future releases. ### Cloud Events Support From 1084a0837eb43d1d2a54acd4bdaefcbb422a8a53 Mon Sep 17 00:00:00 2001 From: Ian Cooper Date: Sat, 25 Oct 2025 20:22:43 +0200 Subject: [PATCH 06/12] chore: fix errors spotted by Claude review --- release_notes.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/release_notes.md b/release_notes.md index 866c68b2eb..718ec6e469 100644 --- a/release_notes.md +++ b/release_notes.md @@ -196,7 +196,7 @@ services.AddBrighter() public override MyResult Handle(MyCommand command) { } // V10 - New approach -[UseResiliencePipeline(policy: "MyPipeline"), step: 1] +[UseResiliencePipeline(policy: "MyPipeline", step: 1)] public override MyResult Handle(MyCommand command) { } ``` @@ -205,7 +205,7 @@ The `TimeoutPolicyAttribute` is now marked as obsolete. The new approach provides: * **Full Polly v8 Support**: Access to all Polly resilience strategies -* **CancellationToken Integration**: Proper cancellation token flow from resilience pipelines ([PR #3698](https://github.com/BrighterCommand/Brighter/pull/3698)) +* **CancellationToken Integration**: Proper cancellation token flow from resilience pipelines * **Enhanced Context**: Request context integration with Polly's resilience context ### Request Context Enhancements @@ -325,8 +325,9 @@ For users upgrading from V9 to V10: 3. **Update Builder Calls**: * Replace messaging builder methods with `AddProducers()`/`AddConsumers()` -4. **Migrate Timeout Policies**: - * Replace `[TimeoutPolicy]` with `[UseResiliencePipeline]` and Polly configuration +4. **Migrate Policies**: + * Replace `[TimeoutPolicy]` with `[UseResiliencePipeline]` and Polly configuration ([TimeoutPolicy is deprecated in V10 and will be removed in V11]) + * Replace `[UsePolicy]` with `[UseResiliencePipeline]` 5. **Message ID Changes**: * Message and Correlation IDs are now strings (defaulting to GUID strings) From 5a7dfffaac1cd5f0f6b2f70336457171faa1cd9b Mon Sep 17 00:00:00 2001 From: Ian Cooper Date: Sat, 25 Oct 2025 20:27:56 +0200 Subject: [PATCH 07/12] chore: fix issues raised by Claude review --- README.md | 2 +- release_notes.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 008748042a..fc6cb83231 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ * You can write a command, that is then dispatched to a handler that you write. * Alternatively you can write an event, that is dispatched to zero or more handlers that you write. * Brighter also supports the Command Processor pattern, so that you can add middleware between the sender and handler. - * Handlers are tagged via attributes to include middleware in thier pipeline. + * Handlers are tagged via attributes to include middleware in their pipeline. * Out-of-the-box middleware is provided for logging and Polly (retry, and circuit breaker). * When integrating two microservices using messaging, one question is how to abstract from the developer the code that sends and receives messages in favor of writing domain code. diff --git a/release_notes.md b/release_notes.md index 718ec6e469..7c3affe307 100644 --- a/release_notes.md +++ b/release_notes.md @@ -19,7 +19,7 @@ With V10 we have made a number of significant changes to Brighter. There are bre ### Cloud Events Support -Full Cloud Events specification support has been added across all transports: +Full Cloud Events specification support has been added across all supported messaging protocols: * **Publication**: Support for Cloud Events on the Publication with configurable additional properties * **Message Mapper**: The Publication is passed into the message mapper, allowing you to read CloudEvents properties @@ -58,7 +58,7 @@ You only need to create custom message mappers when you require explicit transfo .AddProducers((configure) => { ... - } + }) //This is the default mapper type, so you can omit it, but we are explicit for this note to show how to register your own default .AutoFromAssemblies([typeof(TaskCreated).Assembly], defaultMessageMapper: typeof(JsonMessageMapper<>), asyncDefaultMessageMapper: typeof(JsonMessageMapper<>)); ``` @@ -188,7 +188,7 @@ services.AddBrighter() ### Polly Resilience Pipeline -**Breaking Change**: New resilience pipeline attributes replace legacy timeout policies ([PR #3677](https://github.com/BrighterCommand/Brighter/pull/3677)): +**Breaking Change**: New resilience pipeline attributes replace legacy timeout policies ```csharp // V9 - Deprecated @@ -212,7 +212,7 @@ The new approach provides: **Breaking Change**: The `IRequestContext` interface has been enhanced to support: -* **Partition Key**: Set message partition keys dynamically (see [PR #3678](https://github.com/BrighterCommand/Brighter/pull/3678)) +* **Partition Key**: Set message partition keys dynamically * **Custom Headers**: Add headers via request context * **Resilience Context**: Integration with Polly Resilience Pipeline From fa6a731003c08d359194f69e9f9e591c46ffc424 Mon Sep 17 00:00:00 2001 From: Ian Cooper Date: Sat, 25 Oct 2025 20:31:35 +0200 Subject: [PATCH 08/12] chore: more typos --- release_notes.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/release_notes.md b/release_notes.md index 7c3affe307..76f4a49396 100644 --- a/release_notes.md +++ b/release_notes.md @@ -349,7 +349,7 @@ If you use Inbox/Outbox patterns, you may need to update your database schemas. For detailed migration guidance, see the [V10 Migration Guide](https://brightercommand.github.io/Brighter/migration/v10) in our documentation. -## Release 9.X ## +## Release 9.X ## Binary Serialization Fixes @@ -367,7 +367,7 @@ For detailed migration guidance, see the [V10 Migration Guide](https://brighterc * Compression Transform now available to compress messages using Gzip (or Brotli or Deflate on .NET 6 or 7) -## Release 9.3.6 +## Release 9.3.6 * Set correct partition key (kafka key) for Kafka messages * Add default option for Header bags serialisation @@ -391,7 +391,7 @@ For detailed migration guidance, see the [V10 Migration Guide](https://brighterc * Fixed missing negation operator when checking for AWS resources -## Release 9.1.14 +## Release 9.1.14 * Renamed MessageStore to Outbox and CommandStore to Inbox for clarity with well-known pattern names outside this team * Impact is wide, namespaces, class names and project names, so this is a ***BREAKING CHANGE*** @@ -423,13 +423,13 @@ For detailed migration guidance, see the [V10 Migration Guide](https://brighterc * Supports an async pipeline: callbacks should happen on the same thread as the handler (and the pump), avoiding thread pool threads * Fixed issue in SQlite with SQL to mark a message as dispatched -## Release 8.1.1399 +## Release 8.1.1399 * Update nuget libs * RabbitMQ 6.* * Fix correlationid no been sent correctly when using SqlCommandStore -## Release 8.1.1036 +## Release 8.1.1036 * Fixes issue when a rabbitmq connection is dropped it sometimes ends up with 2 connections and then does not dispose the ghost connection. * Fix for System.InvalidOperationException: You cannot enqueue more items than the buffer length #846 @@ -457,13 +457,13 @@ For detailed migration guidance, see the [V10 Migration Guide](https://brighterc * Added support for the Outbox pattern via DepositPost and ClearPostBox * Fixed to allow different exchange types to be set (was broken by support of delayed exchange) -## Release 7.4.0 +## Release 7.4.0 * Updated to signed version of Polly, works with netcore2.1. * Fix for Sql CommandStore. * Fixes to make flaky tests stable. -## Release 7.3.0 +## Release 7.3.0 * Added beta Support for a Redis transport * Support for Binding a channel to multiple topics @@ -473,23 +473,23 @@ For detailed migration guidance, see the [V10 Migration Guide](https://brighterc * Fixed an issue where multiple performers did not have distinct names and so could not be tracked * RMQ changed from push rabbit consumer to just simple pull based. -## Release 7.2.0 +## Release 7.2.0 * Support for PostgreSql Message Store (Tarun Pothulapati @Pothulapati) * Support for MySql Message and Command Stores (Derek Comartin @dcomartin) * Support for Kafka Messaging Gateway - Beta (Wayne Hunsley @whunsley) * Support for MSSql Messaging Gateway - Beta (Fred Hoogduin @Red-F) -## Release 7.1.0 +## Release 7.1.0 * Fixes issue with high CPU when failing to connect to RabbitMQ. * Fixes missing High Availability setting, had to make changes to IAmAChannelFactory. -## Release 7.0.137 - 7.0.143 +## Release 7.0.137 - 7.0.143 * Support for .NET Core (NETSTANDARD 1.5) -**Breaking Changes** +### **Breaking Changes** * Configuration no longer supports XML based config sections. We use data structures instead, and expect you to configure mostly in code, initializing those data structures from your config system of choice yourself. We recommend following 12-Factor Apps guidelines and preferring enviroment variables for items that vary by environment over XML or JSON based configuration files. (We may consider providing config sections in Contrib again, please feedback if this is a critical issue for you. PRs welcome.) * Dropped CommandProcessor from namespaces and folder names, to shorten, and remove semantic issue that it is not just a Command Processor @@ -497,20 +497,20 @@ For detailed migration guidance, see the [V10 Migration Guide](https://brighterc * As a result, your using statements will need revision with this release * Some namespaces i.e Paramore.Brighter.Policy changed to avoid clashes now CamelCase (has become Paramore.Brighter.Policies) -## Release 6.1.0 +## Release 6.1.0 * Support for binary message payloads i.e. not just text/plain for JSON or XML. Current support is modelled around use of protobuf over RMQ -## Release 6.0.28 +## Release 6.0.28 Fix issue with encoding of non-string types and transmission of correlation id -## Release 6.0.6 +## Release 6.0.6 - Increase logging level when we stop reading from a queue that cannot be readhttps://github.com/BrighterCommand/Brighter/pull/179 * Peformance issue caused by creation of a logger per requesthandler instance. The logger is now static, but is initialized lazily and can be overridden for TDD or legacy compatibility -## Release 6.0.0 +## Release 6.0.0 **Breaking Changes** * CommandProcessorBuilder no longer takes .Logger(logger) @@ -531,7 +531,7 @@ Fix issue with encoding of non-string types and transmission of correlation id < * Huge feature, Async; added support for SendAsync and PublishAsync to an IHandleRequestsAsync pipeline. * Basic support for publishing to Azure Service Bus with `paramore.brighter.commandprocessor.messaginggateway.azureservicebus`. -## Release 5 +## Release 5 **Bug Fixes:** @@ -564,7 +564,7 @@ Fix issue with encoding of non-string types and transmission of correlation id < * Dropped support for RavenDb as a message store, we feel EventStore covers this scenario better where non-relational stores are an option * Removed release branch. We just tag a release on master now, so this only existed to support an older version of the library that was pre the tagging strategy. Removed now as confusing to new users of the library. -## Release 4.0.215 +## Release 4.0.215 1. Fixed an issue where you could not have multiple UsePolicy or FallbackPolicy attributes on a single handler.# 2. We pool connections now, to prevent clients with large number of channels overwhelming servers. @@ -575,7 +575,7 @@ Fix issue with encoding of non-string types and transmission of correlation id < 7. Fixed and issues with unhandled exceptions from handlers when an event is published not been logged correctly 8. The first early version of a Message Store Viewer has been release as a zip file download -## Release 3.0.129 +## Release 3.0.129 1. We now support a Fallback method on IHandleRequests which is intended to be used for compensating or emergency action when a Handle method cannot be executed. The [FallbackPolicy] attribute supports the pipeline calling the Fallback method for you, in the event of either any exception bubbling into the handler, or a broken circuit exception bubbling into the handler. 2. Fix issue with RabbitMQ consumers running on a High Availability cluster not cancelling properly after cluster failover. @@ -583,7 +583,7 @@ Fix issue with encoding of non-string types and transmission of correlation id < 4. Added functionality so after a specified number of unacceptable message (unable to read from queue or map message) a connection is shutdown, by default unacceptable message are acked and dropped. 5. Move RequeueException to paramore.brighter.commandprocessor.exceptions (breaking change). -## Release 3 +## Release 3 1. Refactored **IAmAMessagingGateway** into a **IAmAMessageConsumer** and **IAmAMessageProducer** to support differing approaches to producing and consuming messages for a particular flavour of Message-Oriented-Middleware. *These changes are a breaking binary change for users of earlier versions.* 1. NOTE: IF YOU USE TASK QUEUES PLEASE SAVE YOUR SERVICEACTIVATORCONNECTIONS IN YOUR APP.CONFIG AS THE V2.0.1 BRIGHTER.SERVICEACTIVATOR UNINSTALL WILL DELETE THEM (FIXED FOR V3) From b44d740916053c70bfa41e1b81487f39f5bfe7f4 Mon Sep 17 00:00:00 2001 From: Ian Cooper Date: Sat, 25 Oct 2025 20:36:16 +0200 Subject: [PATCH 09/12] chore: update release notes, don't add Sqlite files --- .gitignore | 5 +++++ README.md | 1 - release_notes.md | 46 ++++++++++++++++++++++------------------------ 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index ba1e9b5e76..df935536ea 100644 --- a/.gitignore +++ b/.gitignore @@ -246,6 +246,11 @@ ServiceFabricBackup/ *.ldf *.ndf +# SQlite files +*.db +*.sqlite +*.sqlite3 + # Business Intelligence projects *.rdl.data *.bim.layout diff --git a/README.md b/README.md index fc6cb83231..3955222552 100644 --- a/README.md +++ b/README.md @@ -72,4 +72,3 @@ Portions of this code are based on Stephen Cleary's [AsyncEx's AsyncContext](htt ![CodeScene System Mastery](https://codescene.io/projects/32198/status-badges/system-mastery) ![CI](https://github.com/BrighterCommand/Brighter/workflows/CI/badge.svg) - diff --git a/release_notes.md b/release_notes.md index 76f4a49396..5f68a8f294 100644 --- a/release_notes.md +++ b/release_notes.md @@ -59,13 +59,13 @@ You only need to create custom message mappers when you require explicit transfo { ... }) - //This is the default mapper type, so you can omit it, but we are explicit for this note to show how to register your own default + //This is the default mapper type, so you can omit it, but we are explicit for this note to show how to register your own default .AutoFromAssemblies([typeof(TaskCreated).Assembly], defaultMessageMapper: typeof(JsonMessageMapper<>), asyncDefaultMessageMapper: typeof(JsonMessageMapper<>)); ``` ### Dynamic Message Deserialization -Brighter now supports multiple message types on the same channel through dynamic request type resolution. This enables content-based deserialization where the message type is determined at runtime metadata rather than compile-time generic parameters. We still support the older DataType channel approach. As routing to a handler is based on type, this will decide the handler that receives this message (although see also Agreement Dispatcher). +Brighter now supports multiple message types on the same channel through dynamic request type resolution. This enables content-based deserialization where the message type is determined at runtime from metadata rather than compile-time generic parameters. We still support the older DataType channel approach. As routing to a handler is based on type, this will decide the handler that receives this message (although see also Agreement Dispatcher). ```csharp new KafkaSubscription( @@ -112,6 +112,26 @@ The CommandProcessor now lets you set the `RequestContext` explicitly when calli For consumers, we now add a property to the `RequestContext` that provides the `OriginatingMessage` which allows you to examine properties of the message that was received. +**Breaking Change**: The `IRequestContext` interface has been enhanced to support: + +* **Partition Key**: Set message partition keys dynamically +* **Custom Headers**: Add headers via request context +* **Resilience Context**: Integration with Polly Resilience Pipeline + +```csharp +// Set partition key and custom headers via request context +public class MyHandler : RequestHandler +{ + public override MyCommand Handle(MyCommand command) + { + Context.Span.SetAttribute("custom.header", "value"); + Context.PartitionKey = command.TenantId; + + return base.Handle(command); + } +} +``` + ### Proactor and Reactor We have made significant changes to Brighter's concurrency models. We now use terminology that derives from the Reactor and Proactor patterns, replacing the previous "blocking" and "non-blocking" terminology with clearer semantic meaning. @@ -208,28 +228,6 @@ The new approach provides: * **CancellationToken Integration**: Proper cancellation token flow from resilience pipelines * **Enhanced Context**: Request context integration with Polly's resilience context -### Request Context Enhancements - -**Breaking Change**: The `IRequestContext` interface has been enhanced to support: - -* **Partition Key**: Set message partition keys dynamically -* **Custom Headers**: Add headers via request context -* **Resilience Context**: Integration with Polly Resilience Pipeline - -```csharp -// Set partition key and custom headers via request context -public class MyHandler : RequestHandler -{ - public override MyCommand Handle(MyCommand command) - { - Context.Span.SetAttribute("custom.header", "value"); - Context.PartitionKey = command.TenantId; - - return base.Handle(command); - } -} -``` - ### AWS SDK v4 Support Complete AWS SDK v4 support has been added: From 415048d515b2c07a4d3afb57a4c99ac4745fd54e Mon Sep 17 00:00:00 2001 From: Ian Cooper Date: Sat, 25 Oct 2025 20:51:04 +0200 Subject: [PATCH 10/12] chore: clean up release notes from Claude suggestions, remove cached db --- .gitignore | 2 +- Brighter.sln.DotSettings | 2 +- README.md | 2 +- release_notes.md | 6 +++--- .../WebAPI_Dapper/GreetingsWeb/Greetings.db | Bin 36864 -> 0 bytes .../WebAPI_EFCore/GreetingsWeb/Greetings.db | Bin 36864 -> 0 bytes .../SalutationAnalytics/Salutations.db | Bin 32768 -> 0 bytes 7 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 samples/WebAPI/WebAPI_Dapper/GreetingsWeb/Greetings.db delete mode 100644 samples/WebAPI/WebAPI_EFCore/GreetingsWeb/Greetings.db delete mode 100644 samples/WebAPI/WebAPI_EFCore/SalutationAnalytics/Salutations.db diff --git a/.gitignore b/.gitignore index df935536ea..9f1c9c33b0 100644 --- a/.gitignore +++ b/.gitignore @@ -246,7 +246,7 @@ ServiceFabricBackup/ *.ldf *.ndf -# SQlite files +# SQLite files *.db *.sqlite *.sqlite3 diff --git a/Brighter.sln.DotSettings b/Brighter.sln.DotSettings index 3d8771c936..90d48a28e6 100644 --- a/Brighter.sln.DotSettings +++ b/Brighter.sln.DotSettings @@ -1,2 +1,2 @@ - + False \ No newline at end of file diff --git a/README.md b/README.md index 3955222552..49d493b058 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ | | | | ------------- | ------------- | |![canon](https://raw.githubusercontent.com/BrighterCommand/Brighter/master/images/brightercanon-nuget.png) |[Brighter](https://github.com/BrighterCommand/Brighter)| -||Brighter is a framework for building messaging app with .NET and C#. It can be used with an in-memory bus, or for interoperability in a microservices architecture, out of process via a wider range of middleware transports. | +||Brighter is a framework for building messaging apps with .NET and C#. It can be used with an in-memory bus, or for interoperability in a microservices architecture, out of process via a wider range of middleware transports. | | Version | [![NuGet Version](http://img.shields.io/nuget/v/paramore.brighter.svg)](https://www.nuget.org/packages/paramore.brighter/) | | Download | [![NuGet Downloads](http://img.shields.io/nuget/dt/paramore.brighter.svg)](https://www.nuget.org/packages/Paramore.Brighter/) | | Documentation | [Technical Documentation](https://brightercommand.gitbook.io/paramore-brighter-documentation/) | diff --git a/release_notes.md b/release_notes.md index 5f68a8f294..3e754a8064 100644 --- a/release_notes.md +++ b/release_notes.md @@ -6,13 +6,13 @@ With V10 we have made a number of significant changes to Brighter. There are breaking changes that you will need to be aware of. However, most of the changes required are straightforward to make. A summary of the most important changes: -* **Cloud Events**: We now have full support Cloud Events headers; you can set values in your Publication and have them reflected on messages. +* **Cloud Events**:We now have full support for Cloud Events headers; you can set values in your Publication and have them reflected on messages. * **Open Telemetry**: We now support the OpenTelemetry Semantic Conventions for Messaging. This will mean that you have different traces to V9, where the OTel conventions were Brighter's own. * **Default Message Mappers**: There is no need to provide a mapper if your goal is to serialize your body as JSON. You can use a default mapper. You can create your own default mapper for other formats. You only need explicit mappers for complex transform pipelines. * **Dynamic Message Deserialization**: Previously we required that you used a DataType Channel (one type per channel). Whilst we recommend this, and it remains the default you can now provide a callback to determine the message type from the message itself, such as via the Cloud Events type, before deserializing. * **Agreement Dispatcher**: We now support a callback for determining the handler to dispatch a Command or Event to. Previously we matched request and handler based on the request type. Whilst this is still a default, you can now add a callback to dynamically determine the handler from the request and the request context. * **Request Context Improvements**: You can now inject the RequestContext more easily into a pipeline. The RequestContext now supports the `OriginatingMessage` for subscriptions to queues or streams. -* **Reactor and Proactor**: We have made considerable under-the-hood improvements synchronous and asynchronous message pumps in your consumer. The asynchronous pipeline is now end-to-end. +* **Reactor and Proactor**: We have made considerable under-the-hood improvements to synchronous and asynchronous message pumps in your consumer. The asynchronous pipeline is now end-to-end. * **Scheduled Requests/Messaging**: We now support integration with schedulers, like Quartz.NET, Hangfire, or AWS Scheduler. This can be used with requests or messages. We use this support internally, if available, to allow "Requeue with Delay" where the messaging protocol does not natively support it. * **Nullability**: We have enabled nullable reference types. * **Simplified Configuration**: We have tried to make configuration simpler, including renaming obscure methods. This needs more work in future releases. @@ -24,7 +24,7 @@ Full Cloud Events specification support has been added across all supported mess * **Publication**: Support for Cloud Events on the Publication with configurable additional properties * **Message Mapper**: The Publication is passed into the message mapper, allowing you to read CloudEvents properties * **Default Mappers**: The default `JsonMessageMapper` writes `binary` Cloud Event headers, and the default `CloudEventJsonMessageMapper` writes `structured` Cloud Events Headers. -* **Transport Integration**: We support writing and reading CloudEvents headers across are supported messaging protocols. +* **Transport Integration**: We support writing and reading CloudEvents headers across all supported messaging protocols. * **Message Routing**: Use Cloud Events type for message deserialization (see below). ### OpenTelemetry Integration diff --git a/samples/WebAPI/WebAPI_Dapper/GreetingsWeb/Greetings.db b/samples/WebAPI/WebAPI_Dapper/GreetingsWeb/Greetings.db deleted file mode 100644 index ac9b7971655658bbb3024d17be61f67f2d3bc691..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36864 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 From 19b01fde8b275efdbf39225603fac1848b7c6d55 Mon Sep 17 00:00:00 2001 From: Ian Cooper Date: Sat, 25 Oct 2025 21:13:02 +0200 Subject: [PATCH 11/12] chore: fix typos --- README.md | 2 +- release_notes.md | 29 +++++++++++++++-------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 49d493b058..a9175afafa 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ | Release [X] | The code for an actively supported release. Created when master needs breaking changes that are not compatible with the current release. We support one 'historical' release. | | [Other] | A branch for any work that is not ready to go into master (for example would break CI) or is experimental i.e. we don't know if we intend to ever ship, we are just trying out ideas. | -## Using Docker Compose to test ## +## Using Docker Compose to test We provide a Docker Compose file to allow you to run the test suite, without having to install the pre-requisites, such as brokers or databases locally. diff --git a/release_notes.md b/release_notes.md index 3e754a8064..df02c05f60 100644 --- a/release_notes.md +++ b/release_notes.md @@ -263,6 +263,7 @@ var subscription = new RmqSubscription( * **Updated Defaults**: Improved default configuration values for better out-of-the-box experience **AWS Improvements**: + * **SQS Publication Enhancement**: Allow publishing directly to an SQS queue without SNS * **S3 Claim-Check**: Fixed AWS S3 claim-check implementation @@ -374,8 +375,8 @@ For detailed migration guidance, see the [V10 Migration Guide](https://brighterc ## Release 9.3.0 -- Bug with DynamoDb Outbox and the Outbox Sweeper fixed. The Sweeper required a topic argument supplied by a dictionary of args - * Required adding a Dictionary to various interfaces, which defaults to null, hence the minor version bump as these interfaces have new capabiities +* Bug with DynamoDb Outbox and the Outbox Sweeper fixed. The Sweeper required a topic argument supplied by a dictionary of args + * Required adding a Dictionary to various interfaces, which defaults to null, hence the minor version bump as these interfaces have new capabilities * Internal change to move outstanding message box to a semaphore slim over a mutex as thread-safe. Not strictly neededm, but follows our policy of moving to semaphore slim * Changes to the DynamoDb Outbox implementation as Outstanding Message check was not behaving as expected * The interfaces around Outbox configuration will likely change in v10 to avoid current split and need to configure on both publication and outbox @@ -396,9 +397,9 @@ For detailed migration guidance, see the [V10 Migration Guide](https://brighterc * Mostly you can search and replace to fix * Added support for a global inbox via a UseInbox configuration parameter to the Command Processor * Will insert an Inbox in all pipelines - * Can be overriden by a NoGlobalInbox attribute for don't add to pipeline, or an alternative UseInbox attribute to vary config + * Can be overridden by a NoGlobalInbox attribute for don't add to pipeline, or an alternative UseInbox attribute to vary config * The goal here is to be clearer than our own internal names, which don't help folks who were not part of this team -* The Outbox now fills up if a producer fails to send. You can set an upper limit on your producer, which is the maximum outstanding messages that you want in the Outbox before we throw an exception. This is not the same as Outbox size limits or sweeper, which is seperate and mainly intended if you don't want the Outbox limit to fail-fast on hitting a limit but keep accumulating results +* The Outbox now fills up if a producer fails to send. You can set an upper limit on your producer, which is the maximum outstanding messages that you want in the Outbox before we throw an exception. This is not the same as Outbox size limits or sweeper, which is separate and mainly intended if you don't want the Outbox limit to fail-fast on hitting a limit but keep accumulating results * Added caching of attributes on target handlers in the pipeline build step * This means we don't do reflection every time we build the pipeline for a request * We do still always call the handler factory to instantiate as we don't own handler lifetime, implementer does @@ -412,8 +413,8 @@ For detailed migration guidance, see the [V10 Migration Guide](https://brighterc * Added a matching Publication for producers * Base class includes the attributes that Brighter Core (Brighter & ServiceActivator) need * Derived classes contain transport specific details - * On SQSConnection, renamed VisibilityTimeout to LockTimeout to more generically describe its purpose seperated from GatewayConfiguration, that now has a marker interface, used to connect to the Gateway and not about how we publish or subscribe - * We now have the option to declare infastructure separately and Validate or Assume it exists, still have an option to Create which is the default + * On SQSConnection, renamed VisibilityTimeout to LockTimeout to more generically describe its purpose separated from GatewayConfiguration, that now has a marker interface, used to connect to the Gateway and not about how we publish or subscribe + * We now have the option to declare infrastructure separately and Validate or Assume it exists, still have an option to Create which is the default * We think it will be most useful for environments like AWS where there is a price to checking (HTTP call, and often looping through results) * Added support for a range of parameters that we did not have before such as dead letter queues, security etc via these platform specific configuration files * Provided a short form of the BrighterMessaging constructor, that queries object provided for async versions of interfaces @@ -489,7 +490,7 @@ For detailed migration guidance, see the [V10 Migration Guide](https://brighterc ### **Breaking Changes** -* Configuration no longer supports XML based config sections. We use data structures instead, and expect you to configure mostly in code, initializing those data structures from your config system of choice yourself. We recommend following 12-Factor Apps guidelines and preferring enviroment variables for items that vary by environment over XML or JSON based configuration files. (We may consider providing config sections in Contrib again, please feedback if this is a critical issue for you. PRs welcome.) +* Configuration no longer supports XML based config sections. We use data structures instead, and expect you to configure mostly in code, initializing those data structures from your config system of choice yourself. We recommend following 12-Factor Apps guidelines and preferring environment variables for items that vary by environment over XML or JSON based configuration files. (We may consider providing config sections in Contrib again, please feedback if this is a critical issue for you. PRs welcome.) * Dropped CommandProcessor from namespaces and folder names, to shorten, and remove semantic issue that it is not just a Command Processor * Changed namespaces and folders to be CamelCase * As a result, your using statements will need revision with this release @@ -515,23 +516,23 @@ Fix issue with encoding of non-string types and transmission of correlation id < * In the abstract RequestHandler `logger` is now `Logger` * `RequestLogging` has moved namespace to `paramore.brighter.commandprocessor.logging.Attributes` -**Bug fixes**: +### **Bug fixes**: * Fixed issue #132: concurrent usages of the RabbitMQ messaging gateway would sometimes throw an exception * Fixed issue #134: We no longer use async/await in the command processor. This caused issues with ASP.NET synchronization contexts, resulting in a deadlock when waiting on the thread that was also being used to run the completion. See We wil revisit async when we write *Async versions of the CommandProcesor APIs suitable for using in hosts that can run async code without deadlocking their synchronization context. -* Fixed issue 110: Where we want to log we have two constuctors. A constructor that directly takes an iLog that you provide either directly or via your ioC container; a constructor that defaults that to LogProvider.GetCurrentClassLogger +* Fixed issue 110: Where we want to log we have two constructors. A constructor that directly takes an iLog that you provide either directly or via your ioC container; a constructor that defaults that to LogProvider.GetCurrentClassLogger * In Production code you should set up your log provider and use the constructors that do not take an ILog reference. - * In Test code you should inject the ILog using a fake logger. We don't recommend testing log output, its an implementation detail, unless its an important part of your acceptance criteria for that behaviour. + * In Test code you should inject the ILog using a fake logger. We don't recommend testing log output, its an implementation detail, unless its an important part of your acceptance criteria for that behavior. * This means that your production code should not need to take a direct dependency on Paramore's ILog implementation. * This is a BREAKING CHANGE because we remove the ability to inject the constructor via the *Builder objects, so as to remove the temptation to do that when you should rely on the LibLog framework to wrap your current logger. -**Features:** +### **Features:** * Huge feature, Async; added support for SendAsync and PublishAsync to an IHandleRequestsAsync pipeline. * Basic support for publishing to Azure Service Bus with `paramore.brighter.commandprocessor.messaginggateway.azureservicebus`. ## Release 5 -**Bug Fixes:** +### **Bug Fixes:** * #100 `CommandProcessor.Post` fails with Object reference not set to an instance of an object. * Fix RequeueMessage exhaustion to log ERROR. @@ -542,9 +543,9 @@ Fix issue with encoding of non-string types and transmission of correlation id < * Removed a few unused interfaces. * Correct exceptions namespace to actions. -**Features:** +### **Features:** -* A connection can now be flagged as isDurable in the configuration. Choosing isDurable when using RMQ as the broker will create a durable channel (i.e. does not die if no one is consuming it, and thus continues to subscribe to messages that match it's topic). We think there are sufficient trade-offs with a message store that allows replay to make this setting false by default, but have configured to allow users to make this choice dependent on the characteristics of their consumers (i.e. sufficiently intermittend that messages would be lost). +* A connection can now be flagged as isDurable in the configuration. Choosing isDurable when using RMQ as the broker will create a durable channel (i.e. does not die if no one is consuming it, and thus continues to subscribe to messages that match it's topic). We think there are sufficient trade-offs with a message store that allows replay to make this setting false by default, but have configured to allow users to make this choice dependent on the characteristics of their consumers (i.e. sufficiently intermittent that messages would be lost). * #92 Added [Event Store](https://geteventstore.com/ "Event Store") Message Store implementation * #30 Changed RabbitMQ Messaging Gateway to support multiple performers per connection, fixing the pipeline errors from RabbitMQ Client * Added a UseCommandSourcing attribute that stores commands to a command store. This is the Event Sourcing paradigm described by Martin Fowler in The term Command Sourcing refers to the fact that as described the pattern stores commands (instructions to change state) not events (the results of applying those commands). From 0b921e0b518eaff38294079b1f54dbf4c6c6a7f2 Mon Sep 17 00:00:00 2001 From: Ian Cooper Date: Sat, 25 Oct 2025 23:33:39 +0200 Subject: [PATCH 12/12] remove IDE files --- .gitignore | 1 + Brighter.sln.DotSettings | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 Brighter.sln.DotSettings diff --git a/.gitignore b/.gitignore index 9f1c9c33b0..3c0049d282 100644 --- a/.gitignore +++ b/.gitignore @@ -117,6 +117,7 @@ $tf/ _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user +*.sln.DotSettings # JustCode is a .NET coding add-in .JustCode diff --git a/Brighter.sln.DotSettings b/Brighter.sln.DotSettings deleted file mode 100644 index 90d48a28e6..0000000000 --- a/Brighter.sln.DotSettings +++ /dev/null @@ -1,2 +0,0 @@ - - False \ No newline at end of file