BrighterCommand / BrighterCommand/Brighter
Validate a subscription against its channel factory's ChannelFactoryType at startup
- Dominant language
- C#
- Stars
- 2.5k
- Forks
- 296
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 21
Description
## The defect this would catch
Every messaging gateway's `ChannelFactory` downcasts the `Subscription` it is handed and throws when the cast fails. MSSQL, for example, does it in all three creation methods:
```csharp
// src/Paramore.Brighter.MessagingGateway.MsSql/ChannelFactory.cs:46, :66, :88
MsSqlSubscription? rmqSubscription = subscription as MsSqlSubscription;
if (rmqSubscription == null)
throw new ConfigurationException("MS SQL ChannelFactory We expect an MsSqlSubscription or MsSqlSubscription as a parameter");
```
So `new Subscription(...)` where `MsSqlSubscription` was needed **compiles perfectly and dies when the Dispatcher builds its channels**. Measured, with a control:
```text
Subscription : ConfigurationException: MS SQL ChannelFactory We expect an
MsSqlSubscription or MsSqlSubscription as a parameter
MsSqlSubscription : accepted
```
Two sample applications in this repository carried exactly that bug and **had never been able to start** — see #4331. Nothing noticed, because CI compiles samples and compiling is what this defect survives.
## The data already exists
- `Subscription.ChannelFactoryType` (`src/Paramore.Brighter/Subscription.cs:172`), overridden by each transport's subscription — `MsSqlSubscription` returns `typeof(ChannelFactory)`.
- `CombinedChannelFactory` already matches on it (`CombinedChannelFactory.cs:34`).
- `RegisterConsumerValidationSpecs` already registers four `ISpecification` rules — `PumpHandlerMatch`, `HandlerRegistered`, `RequestTypeSubtype`, `UnwrapTransformResolvable`.
**None of them checks that a subscription is compatible with the channel factory it will be handed.**
## Proposed
A fifth spec comparing `(subscription.ChannelFactory ?? options.DefaultChannelFactory).GetType()` against `subscription.ChannelFactoryType`, reported at `ValidationSeverity.Error` in the style of `PumpHandlerMatch`:
> Subscription '…' is an `Subscription` but will be handed `Paramore.Brighter.MessagingGateway.MsSql.ChannelFactory`, which requires an `MsSqlSubscription` — use `MsSqlSubscription`
That converts "compiles, then dies deep in dispatcher start" into a named startup validation error, **for every transport at once**.
Per `CLAUDE.md`'s TDD rule this belongs behind `/test-first`.
Raised from the documentation work on the MSSQL guide; the maintainer asked for it to be filed rather than left in a PR thread.
Contributor guide
Assessment
This issue has not been assessed yet.