Up to lesson 4.12.3 every service has its data, and every transaction ends at its boundary. An office that wants to take part in a tender needs both, though: The tenders service is to reserve the tender for the office, so that nobody in the office works on it a second time, and the Kladde is to create the draft of a quote. In the past that would have been two rows in one transaction. Now it is two databases. This lesson builds a saga out of it.
A saga instead of a transaction
Microsoft's Azure Architecture Center describes the saga pattern like this: A saga is a sequence of local transactions. Each one runs in one service, changes its database and triggers the next step. If a step fails, compensating transactions undo what the steps before it did. A distributed transaction across two databases, for example with two-phase commit, doesn't fit services that are delivered and operated independently.
The guide distinguishes three kinds of steps:
- Compensable steps: They can be taken back by a step with the opposite effect. The reservation is such a step; its compensation is the release.
- The pivot: the point of no return. Once it is reached, nothing is compensated any more; what comes after has to run to the end. You know the point from lesson 4.6.4. In the participation it is the created quote: As soon as a person works on it, the saga no longer takes it back.
- Retryable steps: They come after the pivot, are idempotent and are repeated until they succeed.
A saga has no isolation. Between its steps others see a half state: a tender that is reserved but has no quote yet. The guide names countermeasures for this; one of them, the semantic lock, is the reservation itself. It tells everyone else: “Someone is working on this right now.”