Introduce specialized stream query handler for CQRS #28
Replies: 1 comment 2 replies
-
I imagine the introduction of the following interfaces: public interface IQueryHandler<in TQuery, TResult>
where TQuery : IQuery
{
ValueTask<TResult> ExecuteAsync(
TQuery query,
CancellationToken cancellationToken);
}
public interface IQuery
{
EventStreamId GetEventStreamId();
} This is essentially a strongly typed, read-only version of the ICommandHandler interface. This would probably also require query specific versions of:
Implementing the IQueryHandler could look something like this: public class MyQueryHandler :
IQueryHandler<MyQuery, MyResult>,
IConsumeEvent<MyEvent>
{
private MyResult result = new();
public ValueTask<MyResult> ExecuteAsync(MyQuery command, CancellationToken cancellationToken)
{
return ValueTask.FromResult(result);
}
public void Consume(MyEvent evt, EventMetadata metadata)
{
// Modify result based on events from stream
}
} From a consumers point of view I imagine using it like this: var processor = serviceProvider.GetRequiredService<IQueryProcessor<MyQuery, MyResult>>();
var query = new MyQuery(streamId, otherStuffPotentiallyUsedByQuery);
var result = await processor.ExecuteAsync(query);
I am still uncertain if we may still want the processor to actually return a result object like CommandResult which could include similar information like stream id, current stream version, and whether the stream exists or not. Something like: public record QueryResult<TResponse>(
EventStreamId Id,
StreamVersion Version,
ResultType Result,
TResponse Response); I am leaning towards just returning the result without wrapping it, but I don't know if there are use cases where it would be beneficial to have the above information included. |
Beta Was this translation helpful? Give feedback.
-
Abstract
There are situations when using a
projection
to build a query side read model is not desirable. One example is producing an audit log from events on a single stream. You can achieve this today by implementing acommand handler
that consumes the desired events to build up an internal read model and return it through thecontext.ResponseObject
property.Motivation
To make these kind of single stream quires more explicit in naming and behaviour a new type of handler could be introduced.
Suggestion
Initial suggestion from @technight
Beta Was this translation helpful? Give feedback.
All reactions