
# إلغاء سير العمل

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

## تسجيل معالج تنظيف

استخدم `on_cancel()` في منشئ سير العمل لتسجيل فئة تُشغّل عند إلغاء سير العمل. يجب أن تنفذ فئة المعالج طريقة `handle( array $state ): void`.

```php
use Queuety\Queuety;

Queuety::workflow( 'import_data' )
    ->then( FetchDataHandler::class )
    ->then( TransformDataHandler::class )
    ->then( LoadDataHandler::class )
    ->on_cancel( ImportCleanupHandler::class )
    ->dispatch( [ 'source_url' => $url ] );
```

يتلقى معالج التنظيف الحالة العامة لسير العمل (كل المفاتيح التي لا تبدأ بـ`_`):

```php
class ImportCleanupHandler {

    public function handle( array $state ): void {
        // Clean up any partial imports.
        if ( isset( $state['temp_table'] ) ) {
            global $wpdb;
            $wpdb->query( "DROP TABLE IF EXISTS {$state['temp_table']}" );
        }

        // Notify the user.
        wp_mail(
            $state['notify_email'] ?? '',
            'Import cancelled',
            'Your data import was cancelled.'
        );
    }
}
```

## الإلغاء عبر PHP

استدعِ `Queuety::cancel_workflow()` باستخدام معرّف سير العمل:

```php
Queuety::cancel_workflow( $workflow_id );
```

تقوم هذه الطريقة بما يلي:

1. تقفل صف سير العمل
2. تضبط حالة سير العمل على `cancelled`
3. تطمر جميع المهام المعلقة والقيد المعالجة لسير العمل مع الرسالة "أُلغي سير العمل"
4. تسجل حدث `workflow_cancelled` وتثبّت التغييرات
5. تشغّل إجراءات التعويض للخطوات المكتملة بترتيب عكسي (إن سُجّلت عبر `compensate_with()`)
6. تشغّل معالج التنظيف `on_cancel` (إن سُجّل)

يُطرح `RuntimeException` إذا كان سير العمل `completed` أو `cancelled` بالفعل.

## الإلغاء عبر CLI

```bash
wp queuety workflow cancel <id>
```

| الخيار | الوصف |
|---|---|
| `<id>` | معرّف سير العمل المراد إلغاؤه (مطلوب) |

```bash
wp queuety workflow cancel 42
```

## ما يحدث عند الإلغاء

عند إلغاء سير عمل:

- **الحالة** تتغير إلى `cancelled`
- **إجراءات تعويض الخطوات** تُنفّذ بترتيب عكسي للاكتمال إذا أُرفقت باستخدام `compensate_with()`
- **معالج التنظيف** يُشغّل بعد وضع علامة `cancelled` على صف سير العمل
- **المهام المعلقة** الخاصة بسير العمل تُطمر فورًا
- **المهام قيد المعالجة** الخاصة بسير العمل تُطمر؛ وعند انتهاء المعالج الجاري، تُهمل مخرجاته ولا يتقدم سير العمل
- **المهام المكتملة** من الخطوات السابقة تظل كما هي
- **إدخال السجل** يُسجل مع الحدث `workflow_cancelled`

## ملغى مقابل فاشل

| الجانب | فشل | أُلغي |
|---|---|---|
| المشغّل | استنفدت خطوة محاولات إعادة المحاولة | استدعاء صريح لـ`cancel_workflow()` |
| الحالة | `failed` | `cancelled` |
| إعادة المحاولة ممكنة | نعم، عبر `retry_workflow()`، ما لم تكن إجراءات التعويض لسير العمل قد نُفذت بالفعل | لا |
| معالج التنظيف | لا يُستدعى | يُستدعى إذا سُجّل عبر `on_cancel()` |
| حدث السجل | `workflow_failed` | `workflow_cancelled` |

## مثال: الإلغاء بعد التأكيد

من الأنماط الشائعة التحقق من حالة سير العمل قبل إلغائه:

```php
$status = Queuety::workflow_status( $workflow_id );

if ( null === $status ) {
    throw new \RuntimeException( 'Workflow not found.' );
}

if ( 'running' === $status->status->value || 'paused' === $status->status->value ) {
    Queuety::cancel_workflow( $workflow_id );
}
```
