Open svalaskevicius opened 9 years ago
... or can projection definition to be simplified and focus be put on composability?
I think now that projection should never emit events - aggregates and sagas should be used instead.
Will leave the ticket to discuss how to compose projections
Hi @svalaskevicius,
I agree that Projections should never emit events. I would also say, sagas neither. Only aggregates should emit events.
IMO, there is two main types of Sagas. Sagas that are run from time to time to bring the system in a consistent state and Sagas to run operations between aggregates.
In the last case, Sagas is just a variation of a Projection. You listen to events from one Aggregate and produce Commands to be sent to another Aggregate.
In Fun.CQRS projections are defined in terms of PartialFunctions and I can compose them with andThen
and orElse
. Return type is still a Future, but I'm planning to refactor it to F[_].
:+1: exactly what I thought as well :)
initially I created this ticket following geteventstore.com but I think staying in pure aggregate/projection/saga definition is better for now
Projections are a scan
/ reduce
over a F[A]
where F[_]
can be akka-stream Source, scala List
, monix Observable
etc. You could compose them by using Kleisli arrows.
In my case, what I mean by Projection is a function Event => Future[Unit]. Actually a PartialFunction[Event, Future[Unit]] that could be refactored to PartialFunction[Event, F[Unit]]. Note, I'm not talking here about Eventflow.
The Projection in my case is only the operation that receives an Event and modify something in the DB.
I'm in principle agree with @rcavalcanti and @svalaskevicius that projections and sagas should not emit events. That's in line with the principles of CQRS. However, in a context of eventual consistency like this, that is inherent in CQRS, how report when the projections were updated?. An user interface may need to know when the data is available and I cannot come up with other solution now that it's not projections emitting events reporting that data is available to be queried.
Hmm at this point I think it's good to separate domain events and UI notifications, which can be done in either pull or push manner :)
@svalaskevicius I agree with the separation of concerns that you mention. But, if you want to notify in a push style, you need to emit an event after projection somehow. OTOH, this event could be the responsibility of the application layer as opposed to the domain layer...
Hmm so for this purpose we could add a notification param for a projection, that is pinged when projection processes some data.
App layer can then use this to update clients.
Is this what you meant?
@svalaskevicius It could be a notification param or even some kind of listener or callback function that the application layer can subscribe to. We need to take into account that typically the application layer might be interested not in only one but in several projections at the same time maybe belonging to several domains.
So, the ability to reason about what projections we are interested in a particular moment it has to rely necessarily on the application layer or on some CEP engine, or whatever, but not on the domain itself.
Anyway, IMHO the projection shouldn't be aware of what its data is going to be used for but should provide a mechanism to enable others to be aware of its update cycle.
Yepp. Agreed :)
projections can emit events that other projections / sagas depend on