Skip to content

Reduce current-state projection boilerplate #591

@louis4li

Description

@louis4li

Problem

Writing a current-state projection currently requires each capability to repeat the same framework plumbing:

  • detect and unpack committed state observations from EventEnvelope
  • resolve StateVersion, LastEventId, and observed timestamp
  • create the read model document
  • dispatch the upsert through projection storage
  • wire the materializer in DI

For simple actor-scoped current-state read models, the only capability-specific part should be the business field mapping from committed state to read model. Repeating the full projector shape makes adding read models feel heavier than it needs to be.

Proposal

Introduce a small helper for ordinary current-state projections, without changing the lower-level projector escape hatch.

Possible shape:

services.AddCurrentStateProjection<TContext, TState, TReadModel>(
    (context, state, info) => new TReadModel
    {
        // business fields only; framework supplies version/timestamp info
    });

Where info exposes framework-derived values such as:

  • RootActorId
  • CommandId / CorrelationId when available
  • StateVersion
  • LastEventId
  • ObservedAt
  • original EventEnvelope / observed payload for advanced but still local mapping needs

The helper should own the repetitive parts:

  • CommittedStateEventEnvelope.TryUnpackState<TState>(...)
  • timestamp resolution
  • version and event id propagation
  • write dispatcher upsert
  • standard idempotency / old-version handling if available in the store path
  • basic DI registration

Non-goals

  • Do not auto-expose actor state as a public read model.
  • Do not introduce a large projection DSL yet.
  • Do not solve multi-actor aggregate projections in this issue.
  • Do not replace custom projectors for timeline, graph, report, audit, search, or live event projections.

Suggested validation

Migrate one simple current-state projector, such as WorkflowExecutionCurrentStateProjector, to the helper and compare the resulting code size/readability. Keep complex artifact projectors unchanged.

Expected outcome

Adding a normal actor-scoped current-state read model should require defining the read model contract and business mapping only, while the projection framework handles envelope/state unpacking, version metadata, and storage plumbing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions