PHPackages                             yaoonline/phpsagas-orchestrator - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. yaoonline/phpsagas-orchestrator

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

yaoonline/phpsagas-orchestrator
===============================

Main component controls and coordinates saga participants

1.0.2(1y ago)085MITPHPPHP ^7.1 || ^8.0

Since Oct 18Pushed 1y agoCompare

[ Source](https://github.com/yaoonline/phpsagas-orchestrator)[ Packagist](https://packagist.org/packages/yaoonline/phpsagas-orchestrator)[ Docs](https://github.com/yaoonline/phpsagas-orchestrator)[ RSS](/packages/yaoonline-phpsagas-orchestrator/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (7)Versions (3)Used By (0)

Saga Orchestrator
=================

[](#saga-orchestrator)

[![codecov](https://camo.githubusercontent.com/68f2e534c4444b431d196ef5a16fb7901976176cecec60f525d67e457a05959b/68747470733a2f2f636f6465636f762e696f2f67682f70687073616761732f6f7263686573747261746f722f6272616e63682f6d61737465722f67726170682f62616467652e7376673f746f6b656e3d50305335484454525447)](https://codecov.io/gh/phpsagas/orchestrator)

Table Of Contents
-----------------

[](#table-of-contents)

- [Introduction](#introduction)
- [Requirements](#requirements)
- [About package](#about-package)
- [Installation](#installation)
- [Getting started](#getting-started)
    - [Configuration](#configuration)
    - [Saga creation](#saga-creation)
- [Internal](#internal)
- [License](#license)

Introduction
------------

[](#introduction)

A [saga](https://en.wikipedia.org/wiki/Long-running_transaction) is a data consistency maintaining mechanism used in distributed systems (such as microservices-based applications) each of which has own database, making it impossible to use ACID.
The saga pattern represents a local transactions sequence executing through asynchronous messaging communication.
It can be seen as an alternative to [2PC protocol](https://en.wikipedia.org/wiki/Two-phase_commit_protocol) saving important microservices architecture advantages such as the possibility of using an appropriate storage for concrete microservices nature, as well as asynchronous messaging for high availability and loose coupling. Also it increased flexibility and scalability due to avoidance of participants blocking.

There are two ways to coordinate the saga execution:

- *choreography* - services publish and subscribes to domain events;
- *orchestration* - execution is managed by special service that controls transactions sequence and said services that they must do. This framework implements that approach.

More details about sagas you can find on the [Chris Richardson site](https://chrisrichardson.net/post/microservices/2019/07/09/developing-sagas-part-1.html) or in his great book [Microservices Patterns](https://microservices.io/book).

Requirements
------------

[](#requirements)

- php: &gt;= 7.1
- ext-json
- [phpsagas/contracts](https://github.com/phpsagas/contracts)
- psr/log: ^1.1

About package
-------------

[](#about-package)

This component is the heart of [phpsagas framework](https://github.com/phpsagas) and is responsible for central coordination of each saga participant local transactions execution. Implementation inspired by [eventuate-tram-sagas framework](https://github.com/eventuate-tram/eventuate-tram-sagas). You can use the orchestrator by one of the following methods:

- *as part of your project* (just a vendor package) by including it in a service, which is a owner of distributed business-transaction;
- *as a standalone project* having own database.

This choice entirely dependent on your preferences. Each of the options carried advantages and drawbacks, for example usage of orchestrator as a separate service can provide possibility of another database usage, as well as deployment on high-performance hardware. However, there are some disadvantages such as an undesirable control logic centralization, as well as a single point of failure.
Usage of orchestrator as a project package is more simple and allows to reduce messaging (using current service transactions as local commands).

Installation
------------

[](#installation)

You can install the package using [Composer](https://getcomposer.org/):

```
composer require yaoonline/phpsagas-orchestrator
```

and add to composer.json

```
"repositories": [
    {
        "type": "vcs",
        "url": "https://github.com/yaoonline/phpsagas-orchestrator.git"
    }
]
```

Getting started
---------------

[](#getting-started)

### Configuration

[](#configuration)

There are some interfaces you have to implement (or use existing implementations):

- `SagaFactoryInterface` - for sagas creation ([test example](tests/_support/Implementation/SagaFactory.php))
- `SagaInstanceRepositoryInterface` - sagas repository ([doctrine implementation](https://github.com/phpsagas/doctrine-bridge))
- `MessagePayloadSerializerInterface` - serialize participant commands data messages ([symfony/serializer implementation](https://github.com/phpsagas/serializer-bridge))
- `SagaSerializerInterface` - serialize sagas data ([symfony/serializer implementation](https://github.com/phpsagas/serializer-bridge))
- `MessageProducerInterface` - messages sender ([symfony/messenger implementation](https://github.com/phpsagas/messenger-bridge)))
- `MessageIdGeneratorInterface` - generate message ids ([uuid implementation](https://github.com/phpsagas/message-id-generator)).

Next, it is necessary to configure base orchestrator services - `Saga Creator` and `SagaReplyHandler`. You can do it using your favourite service-container ([symfony autowiring](https://symfony.com/doc/current/service_container.html#the-autowire-option), [pimple](https://github.com/silexphp/pimple), [PHP-DI](https://php-di.org/), etc) or manually (see below).
After that, the orchestrator is ready to be used. Let's look how that works.

### Saga creation

[](#saga-creation)

Saga must implement `SagaInterface` by providing a type with definition consisting of steps that each distributed transaction participant has to perform. For example, let's consider *Travel Tour Service*. The tour buying may consist of next stages distributed by some services:

- *hotel booking* // Hotel Service
- *tickets booking* // Tickets Service
- *visa obtaining* // Visa Service
- *tour buying* // Tour Service with Orchestrator

So, `BuyTourSaga` definition may seem as follows:

```
class BuyTourSaga
{
    // ...
    public function getSagaDefinition(): SagaDefinition
    {
        $steps = $this
            ->step()
            ->localCommand($buyTourCommand) // withCompensation($rejectTourCommand) // step()
            ->remoteCommand($bookTicketsCommand)
            ->withCompensation($rejectTicketsBookingCommand)
            ->step()
            ->remoteCommand($bookHotelCommand)
            ->withCompensation($rejectHotelBookingCommand)
            ->step()
            ->remoteCommand($obtainVisaCommand) // onReply($obtainVisaReplyHandler)
            ->step()
            ->remoteCommand($confirmHotelBookingCommand) // step()
            ->remoteCommand($confirmTicketsBookingCommand)
            ->step()
            ->localCommand($confirmTourCommand);
        ;

        return $steps->build();
    }

    public function onFinished(string $sagaId, SagaDataInterface $data): void
    {
        // notify request initiator about successful outcome
    }

    public function getSagaType(): string
    {
        return 'buy_tour_saga';
    }

    private function step(): StepBuilder
    {
        return new StepBuilder(new SagaDefinitionBuilder());
    }
}
```

The state machine saga representation: [![Buy tour saga](resources/images/buy_tour_saga_state_diagram.png)](resources/images/buy_tour_saga_state_diagram.png)

The saga execution:
[![Buy tour saga](resources/images/buy_tour_saga_sequence_diagram.png)](resources/images/buy_tour_saga_sequence_diagram.png)

Be careful when creating steps sequence of the saga definition!
Let's say that the Visa Service is a third party project provided VisaObtain API only (with no possibility of cancellation). In that case all compensatable commands should be placed *before* the visa obtaining command being a *pivot transaction* defining the saga outcome ([more details about transactions categories](https://infuerno.github.io/2020/06/02/chris-richardson-microservices.html)).
Also, the each saga lifecycle consists of creation, successful execution or failure that can include some logic implementation (e.g. using [event dispatcher](https://symfony.com/doc/current/components/event_dispatcher.html)) as the request initiator notification upon the saga completion.
The saga can execute both local (same project with orchestrator) and remote commands. The main purpose of the command is to delegate business logic execution to application services and either update saga data (for local commands) or provide data for another microservice's logic execution (for remote commands).

A local command [example](tests/_support/Implementation/TravelTourSaga/Command/BuyTourCommand.php):

```
class BuyTourCommand implements LocalCommandInterface
{
    private $tourService;

    // inject your project service
    public function __construct(TourService $tourService)
    {
        $this->tourService = $tourService;
    }

    /**
     * @param SagaDataInterface|BuyTourSagaData $sagaData
     */
    public function execute(SagaDataInterface $sagaData): void
    {
        // buyTour logic incapsulated behind project service, not here
        $tour = $this->tourService->buyTour(
            $sagaData->getCountry(),
            $sagaData->getCity(),
            $sagaData->getDateFrom(),
            $sagaData->getDateTill()
        );
        // set created tour id to saga data for next commands usage
        $sagaData->setTourId($tour->getId());
    }

    public function getSagaDataType(): string
    {
        return BuyTourSagaData::class;
    }
}
```

A remote command [example](tests/_support/Implementation/TravelTourSaga/Command/BookTicketsCommand.php):

```
class BookTicketsCommand implements RemoteCommandInterface
{
    public function getCommandType(): string
    {
        return 'book_tickets_command';
    }

    public function getSagaDataClassName(): string
    {
        return BuyTourSagaData::class;
    }

    /**
     * Returns data using by another application services.
     *
     * @param SagaDataInterface|BuyTourSagaData $sagaData
     *
     * @return CommandDataInterface
     */
    public function getCommandData(SagaDataInterface $sagaData): CommandDataInterface
    {
        return new BookTicketsData(
            $sagaData->getCountry(),
            $sagaData->getCountry(),
            $sagaData->getDateFrom(),
            $sagaData->getDateTill()
        );
}
```

Local commands results processing may be performed immediately after the current application service call (see above). In order to process remote commands execution results you have to use [ReplyHandler](tests/_support/Implementation/TravelTourSaga/ReplyHandler/BookHotelReplyHandler.php):

```
class BookHotelReplyHandler implements ReplyHandlerInterface
{
    /**
     * @param ReplyMessage                      $message
     * @param SagaDataInterface|BuyTourSagaData $sagaData
     */
    public function handle(ReplyMessage $message, SagaDataInterface $sagaData): void
    {
        if ($message->isSuccess()) {
            $payload = json_decode($message->getPayload(), true);
            $sagaData->setHotelBookingId($payload['hotelBookingId']);
        }
    }
}
```

Internal
--------

[](#internal)

There are three main parts or the orchestrator:

- `BuildEngine` - responsible for saga definition and represents state on execution steps;
- `InstantiationEngine` - provides methods for saga and saga instance creation;
- `ExecutionEngine` - controls saga execution, manages saga state changes:
    - `SagaCreator` - starts saga execution;
    - `SagaReplyHandler` - performs remote commands handling (used by consumers);
    - `SagaActionsProcessor` - controls saga execution, updates and saves saga state.

Saga execution sequence: [![saga internal](resources/images/orchestrator_internal_sequence_diagram.png)](resources/images/orchestrator_internal_sequence_diagram.png)More saga usage details available in [package tests](tests/functional/BuyTourSagaCest.php).

License
-------

[](#license)

Saga orchestrator is released under the [MIT license](LICENSE).

###  Health Score

26

—

LowBetter than 43% of packages

Maintenance37

Infrequent updates — may be unmaintained

Popularity10

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

571d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/5b25500a27efe7c7a24c6fa52c8419974e0fdfd12cebad08f12e7c49a2b0eea5?d=identicon)[yaoonline](/maintainers/yaoonline)

---

Tags

orchestratorsagas

###  Code Quality

TestsCodeception

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/yaoonline-phpsagas-orchestrator/health.svg)

```
[![Health](https://phpackages.com/badges/yaoonline-phpsagas-orchestrator/health.svg)](https://phpackages.com/packages/yaoonline-phpsagas-orchestrator)
```

###  Alternatives

[ecotone/ecotone

Supporting you in building DDD, CQRS, Event Sourcing applications with ease.

558549.8k17](/packages/ecotone-ecotone)[civicrm/civicrm-core

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

728272.9k20](/packages/civicrm-civicrm-core)[phpsagas/orchestrator

Main component controls and coordinates saga participants

3228.0k1](/packages/phpsagas-orchestrator)[j0k3r/php-readability

Automatic article extraction from HTML

186808.8k6](/packages/j0k3r-php-readability)[symfony/ai-platform

PHP library for interacting with AI platform provider.

51927.7k136](/packages/symfony-ai-platform)[symfony/ai-agent

PHP library for building agentic applications.

30536.7k44](/packages/symfony-ai-agent)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
