
# التعويض في سير العمل

يتيح لك التعويض إرفاق معالج تراجع بخطوة مكتملة في سير العمل. يخزّن Queuety لقطة من الحالة العامة عند انتهاء تلك الخطوة، ثم يشغّل معالجات التعويض بترتيب عكسي عند إلغاء سير العمل، أو عند فشله اختياريًا.

## طريقة `compensate_with()`

استدعِ `compensate_with()` مباشرةً بعد الخطوة التي ينبغي التراجع عن آثارها:

```php
use Queuety\Queuety;

Queuety::workflow( 'provision_account' )
    ->then( CreateRemoteUserStep::class )
    ->compensate_with( DeleteRemoteUserCompensation::class )
    ->then( CreateSubscriptionStep::class )
    ->compensate_with( CancelSubscriptionCompensation::class )
    ->then( SendWelcomeEmailStep::class )
    ->dispatch( [ 'user_id' => 42 ] );
```

إذا أُلغي سير العمل لاحقًا، يشغّل Queuety ما يلي:

1. `CancelSubscriptionCompensation`
2. `DeleteRemoteUserCompensation`

## معالجات التعويض

تنفذ معالجات التعويض `Contracts\Compensation`:

```php
use Queuety\Contracts\Compensation;

final class DeleteRemoteUserCompensation implements Compensation {
    public function handle( array $state ): void {
        remote_api_delete_user( $state['remote_user_id'] );
    }
}
```

يتلقى المعالج حالة سير العمل العامة كما كانت مباشرةً بعد اكتمال الخطوة التي يجري التعويض عنها. ولا تُضمّن المفاتيح الداخلية المحجوزة.

## الإلغاء مقابل الفشل

عند الإلغاء الصريح، تُشغّل تعويضات الخطوات المكتملة دائمًا قبل معالج `on_cancel()` الاختياري.

عند الفشل، لا تُشغّل التعويضات إلا إذا اخترت تفعيلها:

```php
Queuety::workflow( 'provision_account' )
    ->then( CreateRemoteUserStep::class )
    ->compensate_with( DeleteRemoteUserCompensation::class )
    ->then( CreateSubscriptionStep::class )
    ->compensate_with( CancelSubscriptionCompensation::class )
    ->then( ChargeCardStep::class )
    ->compensate_on_failure()
    ->dispatch( $payload );
```

من دون `compensate_on_failure()`، يحتفظ سير العمل الفاشل بسجل خطواته المكتملة، ويمكن إعادة المحاولة بدءًا من الخطوة الفاشلة.

مع `compensate_on_failure()`، تُشغّل تعويضات الخطوات المكتملة بعد وضع علامة الفشل على سير العمل. بعد ذلك، يطرح `retry_workflow()` خطأً لأن التعويض عن سير العمل قد تم بالفعل.

## أنواع الخطوات المدعومة

يمكن إرفاق التعويض بما يلي:

- خطوات `then()` المتتابعة
- مجموعات `parallel()`
- خطوات `for_each()`
- خطوات `run_workflow()`
- خطوات التأخير `delay()`
- خطوات الإشارة `wait_for_signal()`
- خطوات تبعية سير العمل `wait_for_workflow()`

بالنسبة إلى `run_workflow()` و`for_each()`، تُسجل لقطة التعويض بعد استقرار العمل المتداخل أو المتشعب بالكامل.

## `on_cancel()` مقابل التعويض

استخدم `compensate_with()` للتراجع عن الآثار الجانبية للخطوات المكتملة بترتيب عكسي.

استخدم `on_cancel()` لخطاف تنظيف واحد على مستوى سير العمل، ينبغي تشغيله كلما أُلغي سير العمل صراحةً.
