You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Ensure that when a broker module gains a runtime-branched AOT serialization registration, a missing AOT serialization opt-in fails at composition or startup time rather than at first message delivery.
Current state on master (verified at 7408c31)
The defect described in the original body is not present in this repository, because the design that would introduce it has not been adopted here.
src/Chatter.MessageBrokers.RabbitMQ/src/Chatter.MessageBrokers.RabbitMQ/DependencyInjection/Extensions.cs:110 registers the Body Converter unconditionally: builder.Services.AddSingleton<IBrokeredMessageBodyConverter, RabbitMqBodyConverter>();. It is a singleton with a type-based service descriptor — no factory delegate, no branch.
RabbitMqBodyConverter (RabbitMqBodyConverter.cs) has no constructor at all; it calls the published Wire Serialization capability ChatterJson.Deserialize<TBody> (line 10) and ChatterJson.Serialize(body) (line 20).
Nothing in the repository registers or resolves a JsonSerializerOptions from DI, and RuntimeFeature.IsDynamicCodeSupported appears nowhere.
The code quoted in the original body comes from a fork PR that is not in this repository's history.
Why this stays open
The hazard it identifies is real and is not currently owned by any other issue. The moment a broker module registers its Body Converter through a factory delegate that resolves an AOT-specific dependency — the shape proposed by #431 and #509 — that dependency is resolved lazily, on the first scope that asks for IBrokeredMessageBodyConverter. In practice that is the first real send or receive, not the AddRabbitMq(...) call. An application that forgets the AOT opt-in would boot cleanly and fail only under production traffic.
Note also the constraint already recorded on src/Chatter.MessageBrokers/CONTEXT.md: a registration factory must not resolve a Brokered Message Receiver's dependency graph from a using var scope, because the scope and every scoped member die as the factory returns while the singleton hosted service keeps the dead graph. Any eager-validation mechanism must respect that, and ADR-0022 ("registration factories open no scope — the component that bounds the graph owns it") is the governing decision.
Reframed scope
This is an acceptance criterion on whichever change first introduces a runtime-branched serialization registration, rather than a standalone defect fix. It should be satisfied by, or explicitly deferred from, #279, #431 and #509.
Decide where eager validation belongs: an IHostedService or IStartupFilter-style check that runs at host start, or a validation pass at registration time. Calling services.BuildServiceProvider() mid-registration is not acceptable — it builds a second container and is the anti-pattern this issue must avoid, not adopt.
Confirm the mechanism honors ADR-0022 and the CONTEXT.md _Avoid_ above: no registration factory may open and close a scope around a graph the caller keeps.
Add a test that boots a host with the broker registered but without the AOT serialization opt-in, and asserts the failure surfaces at startup rather than at first receive. Under a published Native AOT binary this depends on the harness from AOT Phase 0: Infrastructure and red baseline #276.
If the maintainer prefers fewer open items, this is a reasonable candidate to fold into #279 as an explicit acceptance criterion and close.
Goal
Ensure that when a broker module gains a runtime-branched AOT serialization registration, a missing AOT serialization opt-in fails at composition or startup time rather than at first message delivery.
Current state on
master(verified at7408c31)The defect described in the original body is not present in this repository, because the design that would introduce it has not been adopted here.
src/Chatter.MessageBrokers.RabbitMQ/src/Chatter.MessageBrokers.RabbitMQ/DependencyInjection/Extensions.cs:110registers the Body Converter unconditionally:builder.Services.AddSingleton<IBrokeredMessageBodyConverter, RabbitMqBodyConverter>();. It is a singleton with a type-based service descriptor — no factory delegate, no branch.RabbitMqBodyConverter(RabbitMqBodyConverter.cs) has no constructor at all; it calls the published Wire Serialization capabilityChatterJson.Deserialize<TBody>(line 10) andChatterJson.Serialize(body)(line 20).JsonSerializerOptionsfrom DI, andRuntimeFeature.IsDynamicCodeSupportedappears nowhere.WithAotJsonSerializationdoes not exist. Phase 3 (AOT Phase 3: ChatterJson serialization dual-path #279) is still open.The code quoted in the original body comes from a fork PR that is not in this repository's history.
Why this stays open
The hazard it identifies is real and is not currently owned by any other issue. The moment a broker module registers its Body Converter through a factory delegate that resolves an AOT-specific dependency — the shape proposed by #431 and #509 — that dependency is resolved lazily, on the first scope that asks for
IBrokeredMessageBodyConverter. In practice that is the first real send or receive, not theAddRabbitMq(...)call. An application that forgets the AOT opt-in would boot cleanly and fail only under production traffic.Note also the constraint already recorded on
src/Chatter.MessageBrokers/CONTEXT.md: a registration factory must not resolve a Brokered Message Receiver's dependency graph from ausing var scope, because the scope and every scoped member die as the factory returns while the singleton hosted service keeps the dead graph. Any eager-validation mechanism must respect that, and ADR-0022 ("registration factories open no scope — the component that bounds the graph owns it") is the governing decision.Reframed scope
This is an acceptance criterion on whichever change first introduces a runtime-branched serialization registration, rather than a standalone defect fix. It should be satisfied by, or explicitly deferred from, #279, #431 and #509.
IHostedServiceorIStartupFilter-style check that runs at host start, or a validation pass at registration time. Callingservices.BuildServiceProvider()mid-registration is not acceptable — it builds a second container and is the anti-pattern this issue must avoid, not adopt._Avoid_above: no registration factory may open and close a scope around a graph the caller keeps.Chatter.MessageBrokers.RabbitMQ.Chatter.MessageBrokers.SqlServiceBroker(AOT: route JsonUnicodeBodyConverter (SqlServiceBroker) through GetTypeInfo #515) has the identical Body Converter shape.If the maintainer prefers fewer open items, this is a reasonable candidate to fold into #279 as an explicit acceptance criterion and close.
Part of #275.