Skip to content

Fix injecting reducer-backed read models into commands#2304

Merged
woksin merged 3 commits into
mainfrom
fix/reducer-backed-read-model-injection
Jun 17, 2026
Merged

Fix injecting reducer-backed read models into commands#2304
woksin merged 3 commits into
mainfrom
fix/reducer-backed-read-model-injection

Conversation

@woksin

@woksin woksin commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Fixed

  • Injecting a reducer-backed (IReducerFor<T>) read model into a command's CommandValidator<>, Provide(), or Handle() no longer fails at runtime. Reducer-backed read models are now registered for command-scope resolution and resolve by key just like projection-backed and model-bound read models, including the nullable "does not exist" behavior.

woksin and others added 3 commits June 17, 2026 22:44
AddReadModels only built its command-scope read model registrations from
projections and model-bound projections, so a read model materialized by an
IReducerFor<T> reducer was never registered. Injecting one into a
CommandValidator<>, Provide(), or Handle() then failed at runtime even though
the read model existed, while the identical projection-backed read model worked.

Include reducer-backed read model types in the registered set so they resolve
by key through IReadModels exactly like projection-backed ones. Extract the
backing-kind extraction into a ReadModelTargetsFrom helper so the registration
set is a single union and a future backing kind is one line.

Registration stays scoped to read models with a Chronicle backing artifact and
deliberately does not register by the Arc-level [ReadModel] attribute alone,
since that attribute does not imply Chronicle key resolution.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cover the registration, by-key resolution, and end-to-end command pipeline
behavior for reducer-backed read models, alongside the existing projection and
model-bound coverage:

- when_adding_read_models asserts scoped resolvers are registered for
  projection-, model-bound-, and reducer-backed read models.
- when_resolving_a_reducer_read_model_through_di drives the real DI registration
  and resolves a reducer read model to its materialized instance, and to null
  when absent.
- when_injecting_a_reducer_backed_read_model runs the real command pipeline and
  in-process Chronicle event log (mocking only the IReadModels boundary) and
  verifies injection into a CommandValidator<> (active and frozen), Handle(),
  Provide(), and a nullable Handle() parameter.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Clarify in the read models guide that command-scope injection works for read
models backed by a projection, model-bound projection, or reducer, and explain
that the [ReadModel] attribute alone does not make a read model injectable —
key resolution is owned by the backing provider.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@woksin woksin added the patch label Jun 17, 2026
@github-actions

Copy link
Copy Markdown

NuGet packages for this PR, e.g. Cratis.Arc:
https://github.com/cratis/arc/packages/1655206?version=20.43.4

@woksin woksin merged commit d932f33 into main Jun 17, 2026
54 of 55 checks passed
@woksin woksin deleted the fix/reducer-backed-read-model-injection branch June 17, 2026 21:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant