laravel-saga maintained by jeromejhipolito
Description
Laravel package for Saga transaction pattern - manage distributed transactions with automatic rollback support
Author
Last update
2026/01/20 10:43
(dev-main)
License
Downloads
11
Tags
Laravel Saga
Laravel package for implementing the Saga transaction pattern - manage distributed transactions with automatic rollback support.
Features
- Step-by-step execution - Execute multiple steps in sequence with automatic tracking
- Automatic rollback - When a step fails, previously executed steps are automatically rolled back in reverse order
- Database persistence - Transaction and step states are persisted for debugging and recovery
- Status tracking - Detailed status enums for both transactions and steps
- Easy integration - Simple trait for Jobs and Consumers
Installation
composer require jeromejhipolito/laravel-saga
Publish and run the migrations:
php artisan vendor:publish --tag="saga-migrations"
php artisan migrate
Usage
Creating a Saga Step
Create a step by extending AbstractSagaStep:
<?php
namespace App\Saga\Steps;
use JeromeJHipolito\Saga\Steps\AbstractSagaStep;
class CreateOrderStep extends AbstractSagaStep
{
public function execute(array $data): mixed
{
// Create the order
$order = Order::create([
'user_id' => $data['user_id'],
'total' => $data['total'],
]);
return ['order_id' => $order->id];
}
public function rollback(mixed $result, array $data): void
{
// Rollback: Delete the created order
if (isset($result['order_id'])) {
Order::find($result['order_id'])?->delete();
}
}
}
Using the UsesSaga Trait in Jobs
<?php
namespace App\Jobs;
use App\Saga\Steps\CreateOrderStep;
use App\Saga\Steps\ReserveInventoryStep;
use App\Saga\Steps\ProcessPaymentStep;
use JeromeJHipolito\Saga\Traits\UsesSaga;
class ProcessOrderJob implements ShouldQueue
{
use UsesSaga;
public function handle(): void
{
$data = [
'user_id' => $this->userId,
'items' => $this->items,
'total' => $this->total,
];
// Initialize the saga
$saga = $this->initializeSaga($data);
// Add steps
$saga->addStep(new CreateOrderStep())
->addStep(new ReserveInventoryStep())
->addStep(new ProcessPaymentStep());
// Execute - if any step fails, previous steps are rolled back
$this->executeSaga($data);
}
}
Direct Usage with SagaTransactionManager
<?php
use JeromeJHipolito\Saga\Services\SagaTransactionManager;
$saga = SagaTransactionManager::createTransaction(
transactionId: 'order-'.Str::uuid(),
jobClass: 'ProcessOrderJob',
payload: $data
);
$saga->addStep(new CreateOrderStep())
->addStep(new ReserveInventoryStep())
->addStep(new ProcessPaymentStep());
try {
$result = $saga->execute($data);
// Transaction completed successfully
} catch (Exception $e) {
// Transaction failed, steps were rolled back
$saga->rollback(); // Manual rollback for additional cleanup
}
Checking Transaction Status
// Find an existing transaction
$saga = SagaTransactionManager::findByTransactionId('order-123');
$saga->isCompleted(); // true if all steps succeeded
$saga->hasFailed(); // true if any step failed
Transaction and Step Statuses
Transaction Statuses:
PENDING- Transaction created, not yet startedRUNNING- Transaction is executing stepsCOMPLETED- All steps executed successfullyFAILED- A step failed during executionROLLING_BACK- Rollback is in progressROLLED_BACK- Rollback completed
Step Statuses:
PENDING- Step not yet executedEXECUTED- Step completed successfullyFAILED- Step execution failedROLLED_BACK- Step was rolled backCANCELLED- Step was never executed (skipped due to earlier failure)
Database Schema
The package creates two tables:
saga_transactions
id- Primary keyuuid- Unique identifiertransaction_id- Your custom transaction IDjob_class- The class that initiated the sagapayload- JSON payload datastatus- Current transaction statusstarted_at,completed_at,failed_at- Timestampsrollback_started_at,rollback_completed_at- Rollback timestampserror_message- Error details if failed
saga_steps
id- Primary keyuuid- Unique identifiersaga_transaction_id- Foreign key to transactionstep_name- Name of the stepstep_class- Full class name of the stepstep_order- Execution orderstatus- Current step statusexecuted_at,rollback_at- Timestampsresult_data- JSON result from executionerror_message- Error details if failed
Testing
composer test
License
The MIT License (MIT). Please see License File for more information.