
# المواعيد النهائية لسير العمل

يمكن تحديد موعد نهائي لسير العمل. إذا لم يكتمل سير العمل الجاري ضمن المدة المحددة، يضع Queuety علامة الفشل عليه، ويستدعي معالجًا اختياريًا. لا تنتهي صلاحية عمليات سير العمل المتوقفة مؤقتًا أو المنتظرة إشارة أو عمليات سير عمل أخرى أثناء الانتظار. تُفحص المواعيد النهائية مرة واحدة تقريبًا في الدقيقة بواسطة عملية `wp queuety work` طويلة التشغيل، وليس بواسطة عمّال `--once` أو آلية WP-Cron الاحتياطية. يعمل ذلك كآلية إيقاف احتياطية لعمليات سير العمل الطويلة التي ينبغي ألا تستمر إلى ما لا نهاية.

## تحديد موعد نهائي

استخدم `must_complete_within()` في منشئ سير العمل لتحديد أقصى مدة مسموح بها. استخدم `on_deadline()` لتسجيل معالج يعمل عند تجاوز الموعد النهائي.

```php
use Queuety\Queuety;

Queuety::workflow( 'data_import' )
    ->then( FetchDataHandler::class )
    ->then( TransformDataHandler::class )
    ->then( LoadDataHandler::class )
    ->must_complete_within( hours: 24 )
    ->on_deadline( ImportTimeoutHandler::class )
    ->dispatch( [ 'source' => $url ] );
```

تقبل طريقة `must_complete_within()` معاملات مسماة تُجمع قيمها:

```php
->must_complete_within( hours: 2, minutes: 30 )  // 2.5 hours
->must_complete_within( days: 1 )                 // 24 hours
->must_complete_within( seconds: 3600 )           // 1 hour
->must_complete_within( days: 1, hours: 12 )      // 36 hours
```

## معالج الموعد النهائي

يجب أن تنفذ فئة معالج `on_deadline()` طريقة `handle( array $state ): void`. وتتلقى الحالة العامة لسير العمل (كل المفاتيح التي لا تبدأ بـ`_`).

```php
class ImportTimeoutHandler {

    public function handle( array $state ): void {
        // Alert the team.
        wp_mail(
            'ops@example.com',
            'Import workflow timed out',
            'Workflow for source ' . ( $state['source'] ?? 'unknown' ) . ' exceeded its deadline.'
        );

        // Clean up partial work.
        if ( isset( $state['temp_file'] ) ) {
            unlink( $state['temp_file'] );
        }
    }
}
```

معالج الموعد النهائي اختياري. إذا أردت أن يفشل سير العمل دون تشغيل منطق مخصص، فاستخدم `must_complete_within()` دون `on_deadline()`.

## آلية فحص المواعيد النهائية

يفحص العامل المواعيد النهائية المنقضية كل 60 ثانية ضمن حلقة المعالجة. عندما يعثر على سير عمل لا تزال `status` فيه `running` بينما أصبح `deadline_at` في الماضي، يستدعي معالج `on_deadline` إن كان مسجلًا، ويضع علامة الفشل على سير العمل مع رسالة الخطأ `Deadline exceeded`، ويسجل حدث `workflow_deadline_exceeded` في السجل. يُخزن الموعد النهائي نفسه كطابع زمني من نوع `deadline_at` في صف سير العمل، ويُحسب وقت الإطلاق استنادًا إلى المدة المضبوطة.

## ما يحدث عند انتهاء المهلة

عندما تتجاوز سيرورة العمل موعدها النهائي، تتغير حالتها إلى `failed`، وتُضبط رسالة الخطأ على `Deadline exceeded`، ويعمل معالج الموعد النهائي بشكل متزامن إذا كان مسجلًا، ويُسجل إدخال في السجل بمستوى `workflow_deadline_exceeded`. لا تُقاطع المهام قيد التشغيل في منتصف تنفيذها، لكن سيرورة العمل لن تتقدم إلى ما بعد حد الخطوة التي انتهى موعدها. إذا طرح معالج الموعد النهائي نفسه استثناءً، يُلتقط الاستثناء بصمت وتنتهي سيرورة العمل بحالة الفشل.

## طرق WorkflowBuilder

| الطريقة | الوصف |
|---|---|
| `must_complete_within( int $seconds = 0, int $minutes = 0, int $hours = 0, int $days = 0 )` | تعيين الحد الأقصى للمدة المسموح بها. تُجمع جميع المعلمات. |
| `on_deadline( string $handler_class )` | تسجيل معالج يُستدعى عند تجاوز الموعد النهائي. |

## مثال: الموعد النهائي مع إعادة المحاولة

نادرًا ما يكون من المفيد إعادة محاولة سيرورة عمل أخفقت بسبب انتهاء موعدها النهائي. تعيد `retry_workflow()` ضبطها إلى `running` وتعيد إدراج الخطوة المتعثرة في قائمة الانتظار، لكنها لا تمحو الموعد النهائي ولا تمدده، لذا سيؤدي فحص الموعد التالي، خلال نحو دقيقة، إلى إخفاقها مجددًا. أرسل سيرورة عمل جديدة بدلًا من ذلك.

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

if ( 'failed' === $status->status->value ) {
    // Check if it was a deadline failure.
    // You may want to dispatch a new workflow instead of retrying.
    Queuety::retry_workflow( $workflow_id );
}
```

## الموعد النهائي مقابل تأخيرات الانتظار

تنطبق المواعيد النهائية على مدة سيرورة العمل بأكملها. أما تأخيرات الانتظار (`->delay()`) فتوقف سيرورة العمل لمدة محددة ضمن تسلسل خطواتها. ستفشل سيرورة عمل تتضمن تأخير انتظار لمدة ساعة وموعدًا نهائيًا بعد ساعتين إذا استغرقت الخطوات غير المتعلقة بالانتظار أكثر من ساعة إجمالًا.
