Firing a domain event when a Saga is started?

560 views
Skip to first unread message

Marijn Huizendveld

unread,
Aug 7, 2012, 5:21:45 AM8/7/12
to ddd...@googlegroups.com
Hi everybody,

I was wondering if any of you fire an event when a Saga is started.
t seems this is required to get the system back in the right state on a replay…
Is there any general consensus on this?

Cheers,

Marijn

Philip Jander

unread,
Aug 7, 2012, 5:39:44 AM8/7/12
to ddd...@googlegroups.com
Am 07.08.2012 11:21, schrieb Marijn Huizendveld:
> Hi everybody,
>
> I was wondering if any of you fire an event when a Saga is started.
> t seems this is required to get the system back in the right state on a replay�
> Is there any general consensus on this?
>
>

not unless the saga itself is stored using event sourcing.

Generally my sagas are started in response to an event or (less common)
command.
The corresponsing event handler is in the "live" chain of handlers which
is not used when replaying events. So there is no problem.
If you for some reason need to 'deduplicate' the start of a saga, you
could use the correlation id for the saga and only start a new one if
there is no prior saga of that type with the given correlation id.

Cheers
Phil

Greg Young

unread,
Aug 7, 2012, 5:43:43 AM8/7/12
to ddd...@googlegroups.com
Why are you "replaying" sagas? Are they event sourced themselves?
--
Le doute n'est pas une condition agréable, mais la certitude est absurde.

Marijn Huizendveld

unread,
Aug 7, 2012, 5:54:20 AM8/7/12
to ddd...@googlegroups.com
On Aug 7, 2012, at 11:43 AM, Greg Young wrote:

> Why are you "replaying" sagas? Are they event sourced themselves?

Because that usually represents a business event. For example a PayoutSaga: a Customer opens an Account and can receive Payments throughout the month. At the end of the month a PayoutScheduled event results in an actual Payout. What if I realize later on that there is some concept missing in this PayoutSaga? How would I refine this "model" without having it event sourced?

Admittedly I'm having a hard time coming up with a good example, that's probably an "incoherent thought" smell ;-)

Cheers

Greg Young

unread,
Aug 7, 2012, 5:55:38 AM8/7/12
to ddd...@googlegroups.com
So your sagas themselves are event sourced.

Wouldn't the first event be SagaCreated?

Marijn Huizendveld

unread,
Aug 7, 2012, 5:57:17 AM8/7/12
to ddd...@googlegroups.com
On Aug 7, 2012, at 11:39 AM, Philip Jander wrote:

> The corresponsing event handler is in the "live" chain of handlers which is not used when replaying events. So there is no problem.

Seems like a pragmatic approach :-)

Marijn Huizendveld

unread,
Aug 7, 2012, 6:06:46 AM8/7/12
to ddd...@googlegroups.com
On Aug 7, 2012, at 11:55 AM, Greg Young wrote:

> So your sagas themselves are event sourced.

Well I see no reason why they shouldn't be. It is my understanding that Sagas are about long running business transactions and that DDD/CQRS is about proper modeling the business and that using events helps us do that in the most resilient way possible.

> Wouldn't the first event be SagaCreated?

Well SagaCreated is a very clear domain event in our case. A customer can start selling stuff in our application, so as soon as this product is published in our shop by the customer we start tracking the incoming payments for that customer. Receiving payments happens during a finite period which is also ended by another domain event.

So I guess I asked the wrong question in the first place. Is there any reason why your Sagas should or should not be event sourced? Are there arguments in favor or against it?

Philip Jander

unread,
Aug 7, 2012, 1:03:42 PM8/7/12
to ddd...@googlegroups.com
To answer your second question, I see four problems with event sourced
sagas:

1. It can be difficult to define where the saga's events go, since sagas
commonly span across BC boundaries. So they need to be in a kind of
pseudo-BC themselves with its own (logical or physical) event store.
Which leads to a kind of recursive problem - now you need to coordinate
communications of business BCs with that saga-BC. Saga-sagas, maybe? :)

2. You will end up having two look-alike events, one for the aggregate,
one for the saga. E.g. CustomerPlacedOrder and OrderSagaOrderWasPlaced.
Not neccessarily a problem, but not elegant either. On the action side,
you will even have three time the "same" information: saga event,
saga-originated message (=command) and target aggregate event(s).

3. It leads a step further towards a CQRS-as-global-architecture style,
which is Not a good thing(TM).

4. Somewhat related to 3, there is a slight chance that someone at some
point will trigger a saga based not on a domain event but on another
saga's event. Since that is just derived and not guaranteed to stay,
this might lead into a fragile mess.

None of those is a showstopper, but I can't see much value in having the
saga's state transition stored as full-fledged events and named in the
UL. Especially since the saga should only do routing, but not logic.
YMMV of course (and I have done event-sourced sagas without much
difficulty).

Cheers
Phil

gandalf

unread,
Jan 29, 2013, 5:24:38 PM1/29/13
to ddd...@googlegroups.com
Can a saga be implemented like an AR? For example, AR expects commands and generates events. It has state. If we implement Saga the opposite of AR; expecting events and generating commands, would this not work?

Alexey Raga

unread,
Jan 30, 2013, 3:43:26 AM1/30/13
to ddd...@googlegroups.com
I think technically it can be, but it does not make much sense to eventsource process managers (sagas).

Vytautas Mackonis

unread,
Jan 30, 2013, 4:09:06 AM1/30/13
to ddd...@googlegroups.com
Have a look at JOliver's CommonDomain project. It has a simple event sourced saga implementation. The reason why people sometimes like to make sagas event sourced is that they have versioning difficulties.


--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Marijn Huizendveld

unread,
Jan 30, 2013, 4:29:01 AM1/30/13
to ddd...@googlegroups.com
On Jan 30, 2013, at 10:09 AM, Vytautas Mackonis wrote:

> Have a look at JOliver's CommonDomain project. It has a simple event sourced saga implementation. The reason why people sometimes like to make sagas event sourced is that they have versioning difficulties.

Would you mind giving me a link to an example? I can't seem to find a concrete saga implementation in the project, only abstract ones.

Vytautas Mackonis

unread,
Jan 30, 2013, 7:23:04 AM1/30/13
to ddd...@googlegroups.com
I'm afraid I can't provide you with an example because I'm not using them. But it should be quite clear on how they are used from this (and subsequent blog post):



Vytautas Mackonis

unread,
Jan 30, 2013, 7:23:27 AM1/30/13
to ddd...@googlegroups.com

Marijn Huizendveld

unread,
Jan 30, 2013, 7:29:06 AM1/30/13
to ddd...@googlegroups.com
Thanks!

gandalf

unread,
Jan 30, 2013, 9:33:03 AM1/30/13
to ddd...@googlegroups.com
I looked at his implementation but I don't see any tests or sample implementations with it. For example, where would I send commands in that saga implementation? He has a Dispatch method (protected), and adds dispatched messages (I think this is how I am supposed to send a command with) to a field to later add to headers of the stream. Does anyone have a sample code to point me to so I can wrap my head around this?

Thanks
 


On Wednesday, January 30, 2013 7:29:06 AM UTC-5, Marijn wrote:
Thanks!

Vytautas Mackonis

unread,
Jan 30, 2013, 10:12:15 AM1/30/13
to ddd...@googlegroups.com
The basic idea is that the list of commands that are to be dispatched is stored as out of band data and later dispatched by the event store itself. Here's a sample dispatcher (with all the nitty-gritty removed) for his event store that does exactly that:

    public class SagaCommitDispatcher: IDispatchCommits
    {
        private readonly IBus _bus;

        public SagaCommitDispatcher(IBus bus)
        {
            _bus = bus;
        }

        public void Dispatch(Commit commit)
        {
            const string SagaUndispatchedMessagePrefix = "UndispatchedMessage.";
            //extract commands from headers
            foreach (var header in commit.Headers.Where(x => x.Key.StartsWith(SagaUndispatchedMessagePrefix)).OrderBy(x => x.Key))
            {
                var command = header.Value;
_bus.Send(command);
            }
        }
        public void Dispose()
        {
        }
    }

The key thing to notice here is that the events themselves stored in the event store are not published. They are only used to rebuild saga state.


gandalf

unread,
Jan 30, 2013, 12:51:27 PM1/30/13
to ddd...@googlegroups.com
Oh yes, I forgot about that commit dispatcher interface.

Does it make sense to have a separate event store for saga events to keep things simple?

gandalf

unread,
Jan 30, 2013, 12:52:15 PM1/30/13
to ddd...@googlegroups.com
Thank you for your response by the way! :)

Vytautas Mackonis

unread,
Jan 30, 2013, 5:13:34 PM1/30/13
to ddd...@googlegroups.com
I guess the separate store thing is a matter of personal preference. I had it in separate store simply because deciding whether it's an aggregate or saga related commit is dodgy at best (what if a saga does not dispatch anything for this event?). There are also more concerns, such as BC isolation and event replayability.
Reply all
Reply to author
Forward
0 new messages