Skip to content

Coordinate across Domains ​

One Service UseCase coordinates Orders and Billing through ConfirmOrder and PaymentGateway. It never calls an Action from another Action or one UseCase from another UseCase.

Before you begin ​

Run composer run reference:test:coordination and read cross-domain coordination.

Put the transaction in the coordinator ​

examples/reference-app/app/Pulsar/Services/Client/Modules/Orders/UseCases/FinalizeOrderPayment.php — One Service UseCase coordinates [Domain](/concepts/domain) Action and [Contract](/concepts/contract).

php
<?php

namespace App\Pulsar\Services\Client\Modules\Orders\UseCases;

use App\Pulsar\Domain\Billing\Contracts\PaymentGateway;
use App\Pulsar\Domain\Orders\Actions\ConfirmOrder;
use App\Pulsar\Domain\Orders\Models\Order;
use Illuminate\Support\Facades\DB;

final class FinalizeOrderPayment
{
    public function __construct(private readonly ConfirmOrder $confirmOrder, private readonly PaymentGateway $gateway) {}

    public function gatewayName(): string
    {
        return $this->gateway->name();
    }

    // #region cross-domain-coordination
    public function execute(int $orderId, string $idempotencyKey): Order
    {
        return DB::transaction(function () use ($orderId, $idempotencyKey): Order {
            $order = Order::query()->lockForUpdate()->findOrFail($orderId);
            $this->gateway->charge($order->amount_cents, $idempotencyKey);

            return $this->confirmOrder->execute($order);
        });
    }
    // #endregion
}

Verify and troubleshoot ​

The focused test confirms the Order after the fake payment boundary succeeds. Extract shared branching to an Operation when multiple UseCases need it; never hide workflow coordination in an Action.