Repository navigation
Replies: 3 comments
|
You can work around this w/ a custom IVariableSource for both CallerContext and the ICallerContext. Or really just make ICallerContext a "derived variable". Wolverine has chugged along for years without anyone needing to do this, and I'm not enthusiastic about making big changes just to accommodate this. Converting to a discussion. |
0 replies
|
Yeah closing this, lol. Was spiking an implementation, sorry for the noise 😞 |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Describe the bug
When both a concrete type and its interface are on the
AlwaysUseServiceLocationForallow-list, and one handler chain needs both, the generator emits two locals with the same name and the chain fails to compile:The local name appears to be derived from the type name with a leading
Istripped, soCallerContextandICallerContextboth becomecallerContext. The second error follows from the first: the call site then binds the wrong variable.Why both are on the list.
CallerContextis scoped and mutable — one instance per message scope, populated by the handler that scopes it to a tenant — so the generator emittingnew CallerContext()would break the single-instance-per-scope invariant.ICallerContextis a read-only view over that same instance, registered asAddScoped<ICallerContext>(sp => sp.GetRequiredService<CallerContext>()), which is a lambda factory and therefore opaque. Both genuinely have to come from the scope, and both are reachable from one chain: the handler wrapper takes the writable type, and a service in the graph beneath it takes the read-only one.Registrations
Shape that triggers it — a handler whose own dependency takes
ICallerContext, wrapped by something takingCallerContext:Generated code (trimmed;
dotnet run -- codegen test):Expected behavior
Two distinct service types should get two distinct local names — e.g. suffixing on collision (
callerContext2), or deriving the name from the full type name rather than the interface-stripped one.Why it is easy to miss
The failure surfaces when a chain is resolved, not when the host starts. With
TypeLoadMode.Dynamicthat is on first message, so:In our case a projection handler silently stopped running and the only visible symptom was a stale read model.
dotnet run -- codegen testcatches it, and we have added that to CI, but the runtime symptom is entirely silent — so a naming collision reads as a working system.Version
WolverineFx.SqlServer,WolverineFx.EntityFrameworkCore,WolverineFx.RuntimeCompilation)Related but not the same
AlwaysUseServiceLocationFor, but about which services get located rather than what they are named.Workaround
Name a contract higher up the graph on the allow-list so the generator stops descending before it reaches both caller types.
All reactions