Skip to content

Runtime: Command Router stream send primitives #282

Description

@Skymly

Parent

#256

Related

Supersedes the Runtime portion of #265 (split after stream API lock). Sibling slices: SourceGenerators #265; Docs (filed with this split).

What to build

Ship Command Router stream send runtime primitives: progressive IAsyncEnumerable results on the same router domain, without a separate Stream Request Router. Non-stream SendAsync / TrySendAsync paths remain unchanged.

Locked decisions

  • Handler: IStreamCommandHandler<in TCommand, out TItem> with IAsyncEnumerable<TItem> HandleAsync(TCommand, CancellationToken)
  • Router: SendStreamAsync<TCommand, TItem> + TrySendStreamAsync<TCommand, TItem> on ICommandRouter (Try* returns CommandSendAttempt<IAsyncEnumerable<TItem>>)
  • Same TCommand cannot register both non-stream and stream handler (shared 1:1 bijection map)
  • Manual CommandRouterBuilder.Register<TCommand, TItem>(IStreamCommandHandler<TCommand, TItem>)
  • No stream pipeline behaviors in this slice
  • Attribute / generator binding is not this ticket (SourceGenerators SourceGenerators: Command Router stream send capability #265)
  • netstandard2.0: reference Microsoft.Bcl.AsyncInterfaces so IAsyncEnumerable is public on both TFMs
  • Core still has no MSDI/Autofac reference

Acceptance criteria

  • Public IStreamCommandHandler<TCommand, TItem> + SendStreamAsync / TrySendStreamAsync on ICommandRouter
  • CommandRouterBuilder can register stream handlers; duplicate command type (vs void/result/stream) throws
  • Missing stream handler: SendStreamAsync throws CommandHandlerNotFoundException; TrySendStreamAsync returns Failed
  • Contract mismatch (non-stream registered, stream send — and reverse) throws InvalidOperationException
  • Progressive yield covered by unit tests; existing non-stream tests remain green
  • XML docs; dual TFM (netstandard2.0 + net8.0)
  • No source generator / Design Doc / diagnostic ID work in this PR

Blocked by

None — can start immediately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestready-for-agentFully specified, ready for an AFK agent

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions