1. Go to this page and download the library: Download sients/compensator library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
sients / compensator example snippets
use Compensator\Compensator;
use Compensator\CompensatorContext;
class ChargePayment implements \Compensator\Contracts\CompensatorStep
{
public function execute(CompensatorContext $context): mixed
{
$payment = PaymentGateway::charge($context->get('amount'));
$context->set('payment_id', $payment->id);
return $payment;
}
public function compensate(CompensatorContext $context): void
{
PaymentGateway::refund($context->get('payment_id'));
}
}
class CreatePartnerPolicy implements \Compensator\Contracts\CompensatorStep
{
public function execute(CompensatorContext $context): mixed
{
$policy = PartnerApi::createPolicy($context->all());
$context->set('policy_id', $policy->id);
return $policy;
}
public function compensate(CompensatorContext $context): void
{
PartnerApi::cancelPolicy($context->get('policy_id'));
}
}
$result = (new Compensator())
->addStep(new ChargePayment())
->addStep(new CreatePartnerPolicy())
->step(
execute: fn ($ctx) => Pdf::generate($ctx->get('policy_id')),
// compensate is optional — omit it for a step with nothing to undo
name: 'generate_pdf',
)
->run(new CompensatorContext(['amount' => 4999]));
if ($result->needsManualCleanup()) {
// The chain failed AND rollback failed — a side effect is stranded.
foreach ($result->compensationFailures as $failure) {
logger()->critical('stranded side effect', [
'step' => $failure->stepName, // 'ChargePayment'
'attempts' => $failure->attempts,
'error' => $failure->exception->getMessage(),
'context' => $result->context->snapshot(redact: ['card_number']),
]);
}
}
->addStep(new ChargePayment()) // 'ChargePayment'
->addStep(new ChargePayment(), 'retry_charge') // or override it
$compensator = app(Compensator::class); // a new, empty chain every time
use Compensator\Enums\CompensationFailureStrategy;
(new Compensator())
->withFailureStrategy(CompensationFailureStrategy::StopOnFirstFailure)
// ...
(new Compensator())
->retryCompensation(times: 2, sleepMs: 200)
// ...
public function compensate(CompensatorContext $context): void
{
$payment = PaymentGateway::find($context->get('payment_id'));
if ($payment?->isRefundable()) {
$payment->refund();
}
}
(new Compensator())
->compensateFailedStep()
// ...
public function compensate(CompensatorContext $context): void
{
if (! $context->has('payment_id')) {
return;
}
PaymentGateway::refund($context->get('payment_id'));
}
final class CreateOrder implements CompensatorStep
{
public function execute(CompensatorContext $context): mixed
{
// Atomic within this step, committed before the next one starts.
$order = DB::transaction(fn () => Order::create([...]));
$context->set('order_id', $order->id);
return $order;
}
public function compensate(CompensatorContext $context): void
{
DB::transaction(fn () => Order::whereKey($context->get('order_id'))->delete());
}
}
use Illuminate\Support\Facades\Event;
use Compensator\Events\CompensationFailed;
Event::listen(function (CompensationFailed $e) {
logger()->critical('compensation failed', ['step' => $e->stepName]);
});
(new Compensator())
->protectAgainstFatals()
->addStep(new ChargePayment())
// ...
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.