Review what Rinat Abdullin wrote about evolving business process. In particular, notice his recommendation for developing a business process in a fast changing environment -- a process manager is "just" an automated replacement for a human being staring at a screen.
My own mental model of a process manager is that it is an event sourced projection that you can query for a list of pending commands.
Do I need to persist the process manager? It seems like I do, but I'm not sure
It's a read model. You can rebuild the process manager from the history of events each time you need it; or you can treat it like a snapshot that you update.
If I do, I need to save the events for the process manager.
No - the process manager is a manager. It doesn't do anything useful on its own; instead it tells aggregates to do work (ie, make changes to the book of record).
How do I know what basket the ProductReserved events are for? Is it OK to have a BasketId on those too, or is that leaking info
Sure. Note: in most "real" shopping domains, you wouldn't insist on reserving inventory before processing an order; it adds unnecessary contention to the business. It's more likely that your business would want to accept the order, then apologize in the rare case that the order can't be fulfilled in the required time.
How do I keep a relationship between events, how do I know which ItemAdded produced which ProductReserved event?
Messages have meta data - in particular, you can include a causationIdentifier (so you can identify which commands produced which events) and a correlationIdentifier, to generally track the conversation.
For instance, the process manager writes its own id as the correlationId in the command; the events produced by a copy the correlation id of the command, and your process manager subscribes to all events that have its own correlationId.
Should I implement the Basket as a process manager instead of a simple aggregate?
My recommendation is no. But Udi Dahan has a different opinion that you should review; which is that CQRS only makes sense if your aggregates are sagas -- Udi used saga in the place where process manager has become the dominant spelling.
should process managers retrieve aggregates?
Not really? Process managers are primarily concerned with orchestration, not domain state. An instance of a process will have "state", in the form of a history of all of the events that they have observed -- the correct thing to do in response to event Z depends on whether or not we have seen events X and Y. So you may need to be able to store and load a representation of that state (which could be something flat, or could be the history of observed events).
(I say "not really" because aggregate is defined vaguely enough that it's not completely wrong to claim that list of observed events is an "aggregate". The differences are more semantic than implementation -- we load process state and then decide what messages to send to the parts of the system responsible for domain state. There's a bit of hand waving going on here.)
So the PM does not need to use one type of state management over another because it is only responsible for doing stuff live and never during replays?
Not quite - state management isn't a do-er, it's a keeper tracker of-er. In circumstances where the process manger shouldn't emit any signals, you give it inert connections to the world. In other words, dispatch(command)
is a no-op.
Is CQRS a relatively complicated and costly pattern ? Yes.
Is it over-engineering ? Absolutely not.
In the original article where Martin Fowler talks about CQRS you can see a lot of warnings about not using CQRS where it's not applicable:
Like any pattern, CQRS is useful in some places, but not in others.
CQRS is a significant mental leap for all concerned, so shouldn't be tackled unless the benefit is worth the jump.
While I have come across successful uses of CQRS, so far the majority of cases I've run into have not been so good...
Despite these benefits, you should be very cautious about using CQRS.
...adding CQRS to such a system can add significant complexity.
My emphasis above.
If your application is using CQRS for everything, than it's not CQRS that's over-engineered, it's your application. This is an excellent pattern to solve some specific problems, especially high performance/high volume applications where write concurrency may be a major concern.
And it may not be the entire application, but only a small part of it.
A live example from my work, we employ CQRS in the Order Entry system, where we cannot lose any orders, and we do have spikes where thousands of orders come at the same time from different sources, in some specific hours. CQRS helped us to keep the system alive and responsive, while allowing us to scale well the backend systems to process these orders faster when needed (more backend servers) and slower/cheaper when not needed.
CQRS is perfect for the problem where you have several actors collaborating in the same set of data or writing to the same resource.
Other than that, spreading a pattern made to solve a single problem to all your problems will just create more problems to you.
Some other useful links:
http://udidahan.com/2011/04/22/when-to-avoid-cqrs/
http://codebetter.com/gregyoung/2012/09/09/cqrs-is-not-an-architecture-2/
Best Answer
Broadly speaking, an event handler should notify the client if the client is (or might be) interested in the information.
However, the granularity of the message is important.
Remember that whenever you end up passing information over the network you move from the realm of sub-microsecond processing to multi-milliseconds of elapsed time.
For this reason, I'm not convinced the fine granularity of events that you described is appropriate.
Jim Webber has a fair bit to say on the subject, recommending that the granularity should be similar to what you'd use if the service was an actual person in a mid to large size business. In your case, a single CustomerUpdated message instead of multiple smaller messages.