BrighterCommand / BrighterCommand/Brighter

Validate a subscription against its channel factory's ChannelFactoryType at startup

Open
#4,334 0 comments 0 reactions 1 assignee Claimed by @iancooper View on GitHub
0 - Backlog
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.