0

I came across following code:

  public class ShippingSaga : Saga<ShippingSagaData>,
         ISagaStartedBy<OrderAccepted>,
         ISagaStartedBy<CustomerBilledForOrder>
     {
        public void Handle(CustomerBilledForOrder message)
         {
             this.Data.CustomerHasBeenBilled = true;
             this.Data.CustomerId = message.CustomerId;
             this.Data.OrderId = message.OrderId;

             this.CompleteIfPossible();

        }

        public void Handle(OrderAccepted message)
        {
            this.Data.ProductIdsInOrder = message.ProductIdsInOrder;
            this.Data.CustomerId = message.CustomerId;
            this.Data.OrderId = message.OrderId;

            this.CompleteIfPossible();
        }

        private void CompleteIfPossible()
        {
            if (this.Data.ProductIdsInOrder != null && this.Data.CustomerHasBeenBilled)
            {
                this.Bus.Send<ShipOrderToCustomer>(
                    (m =>
                    {
                        m.CustomerId = this.Data.CustomerId;
                        m.OrderId = this.Data.OrderId;
                        m.ProductIdsInOrder = this.Data.ProductIdsInOrder;
                    }
                    ));

                this.MarkAsComplete();
            }
      }
}

By the look of things in above code sagas seem to be some kind of higher level co-ordinator/controller of events. Is this true ?If so ,are they used only in Event Driven Architectures? And at last , are sagas parts of INFRASTRUCTURE?

first query seems to be answered. but where do they really belong in terms of responsibility i.e. Infrastrucure ? Domain ? . are these applicable to only EDAs?

aspxsushil
  • 514
  • 1
  • 5
  • 16
  • 2
    Possible duplicate of [CQRS sagas - did I understand them right?](http://stackoverflow.com/questions/13489829/cqrs-sagas-did-i-understand-them-right) – jlvaquero Jan 13 '17 at 11:01
  • What you are describing is a ProcessManager, a Saga (by its original definition) is described by multiple ProcessManager and a compensation actions for each steps. Most of the time though, people use Saga to describe a ProcessManager. – Boris Guéry Jan 17 '17 at 11:43

1 Answers1

3

Warning: there's some confusion, especially around on the definition of "Saga"; see below.

Process Managers are, fundamentally, read models -- you rehyrdrate them from a history of events, and query them for a list of commands that should be run.

They are analogous to a human being looking at a view, and sending commands to the write model. See Rinat Abdullin's essay Evolving Business Processes for more on this viewpoint.

They serve as a description of the business process, which is to say that they identify additional decisions (commands) that should be run by the aggregates. In implementation, they are very much state machines - given event X and event Y, the process manager is in state(XY), and the commands that it will recommend are fixed.

I find them easier to think about if you tease apart the state machine (which is pure logic) from the side effects (interactions with the bus).

public class ShippingSaga : Saga,
     ISagaStartedBy<OrderAccepted>,
     ISagaStartedBy<CustomerBilledForOrder>
{
    public void Handle(CustomerBilledForOrder message)
    {
        this.process.apply(message);
        this.CompleteIfPossible();
    }

    public void Handle(OrderAccepted message)
    {
        this.process.apply(message);
        this.CompleteIfPossible();
    }

    private void CompleteIfPossible()
    {
        this.process.pendingCommands().each ( m=>
            this.Bus.Send(m);
        }
    }
}

Or equivalently -- if you prefer to think about immutable data structures

public class ShippingSaga : Saga,
     ISagaStartedBy<OrderAccepted>,
     ISagaStartedBy<CustomerBilledForOrder>
{
    public void Handle(CustomerBilledForOrder message)
    {
        this.process = this.process.apply(message);
        this.CompleteIfPossible();
    }

    public void Handle(OrderAccepted message)
    {
        this.process = this.process.apply(message);
        this.CompleteIfPossible();
    }

    private void CompleteIfPossible()
    {
        this.process.pendingCommands().each ( m=>
            this.Bus.Send(m);
        }
    }
}

So the shipping process is defined in terms of the business domain, and the NServiceBus "Saga" interfaces that bit of business domain with the bus infrastructure. Isn't separation of concerns wonderful.

I use "Saga" in quotes because -- the NService bus sagas aren't a particularly good fit for the prior use of the term

The term saga is commonly used in discussions of CQRS to refer to a piece of code that coordinates and routes messages between bounded contexts and aggregates. However, for the purposes of this guidance we prefer to use the term process manager to refer to this type of code artifact. There are two reasons for this:

  • There is a well-known, pre-existing definition of the term saga that has a different meaning from the one generally understood in relation to CQRS.
  • The term process manager is a better description of the role performed by this type of code artifact.
Community
  • 1
  • 1
VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91