
# ضوابط حماية سير العمل

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

للاطلاع على نموذج الموارد الأوسع الذي يشمل قبول المهام الواردة وبيانات تكلفة كل مهمة، راجع [إدارة الموارد](https://queuety.inline0.dev/ar/docs/features/resource-management).

## أضف إصدارًا إلى تعريف سير العمل

استخدم `version()` لإرفاق تسمية إصدار على مستوى التطبيق بتعريف سير العمل:

```php
Queuety::workflow( 'research_run' )
    ->version( 'research.v2' )
    ->then( PlanResearchStep::class )
    ->then( DraftResearchSummaryStep::class )
    ->dispatch();
```

يُخزن الإصدار مع حالة سير العمل، ويُتاح عبر `workflow_status()`، وتطبعه `wp queuety workflow status`، كما يُضمّن في عمليات تصدير سير العمل.

يخزن Queuety أيضًا `definition_hash` حتميًا لكل تشغيل لسير العمل. وتُشتق قيمة التجزئة من تعريف سير العمل المتسلسل، وهي مفيدة عندما تحتاج إلى تحديد بنية سير العمل التي ينفذها تشغيل جارٍ تحديدًا بعد النشر.

## اجعل الإرسال مقاومًا للتكرار

استخدم `idempotency_key()` عندما يُحتمل أن يعيد المستدعون الطلب نفسه:

```php
Queuety::workflow( 'research_run' )
    ->idempotency_key( 'brief:42:research' )
    ->then( PlanResearchStep::class )
    ->dispatch( [ 'brief_id' => 42 ] );
```

إذا أُرسل سير عمل مجددًا بمفتاح سبق استخدامه، فسيعيد Queuety معرّف سير العمل الأصلي بدلًا من إنشاء تشغيل مكرر. المفاتيح عامة عبر أسماء مسارات العمل، لذا أدرج اسم سير العمل في المفتاح عندما يُحتمل أن تشترك مسارات عمل مختلفة في المفتاح نفسه.

يفيد هذا خصوصًا في:

- نقاط النهاية API التي قد يعيد العملاء أو البوابات محاولة الاتصال بها
- مستهلكي webhook الذين قد يتلقون عمليات تسليم مكررة
- خطوات المخطِّط التي ينبغي ألا تنشئ سوى تشغيل تنسيق واحد لكل كيان خارجي

تُخزن مفاتيح منع التكرار في جدول `queuety_workflow_dispatch_keys`.

## حدّد ميزانيات سير العمل

استخدم ميزانيات سير العمل لإفشال عمليات التشغيل التي تتجاوز الحدود التي خططت لها:

```php
Queuety::workflow( 'research_run' )
    ->max_transitions( 20 )
    ->max_for_each_items( 12 )
    ->max_state_bytes( 32768 )
    ->max_cost_units( 40 )
    ->max_started_workflows( 8 )
    ->then( PlanResearchStep::class )
    ->for_each( 'tasks', ExecuteResearchTask::class, 'results' )
    ->dispatch();
```

### `max_transitions()`

يحدّد هذا عدد خطوات سير العمل التي يمكن أن تكتمل قبل فشل التشغيل. ويفيد في حماية مسارات العمل التي تتفرع ديناميكيًا أو قد تعود إلى المنطقة نفسها عبر `_next_step`.

### `max_for_each_items()`

يحدّد هذا عدد العناصر المكتشفة أثناء التشغيل التي يمكن لخطوة `for_each()` واحدة توسيعها. ويفيد في أنظمة المخطِّط والمنفّذ، حيث قد يكتشف وكيل أعمال فروع أكثر بكثير مما هو مقصود.

### `max_state_bytes()`

يحدّد هذا الحجم المرمّز لحالة سير العمل العامة. ويساعد ذلك على منع مسارات العمل طويلة التشغيل من التحول إلى كتل كبيرة يصعب فحصها أو تصديرها أو إعادة محاولتها.

### `max_cost_units()`

يحدّد هذا إجمالي وحدات التكلفة التي تستهلكها الخطوات المكتملة. وتأتي وحدات التكلفة من بيانات الخطوة أو المهمة التي يحلّها Queuety عند إدراج العمل في قائمة الانتظار. ويكون الافتراضي لأعمال المستخدم العادية هو `1`، بينما تستخدم عناصر التنسيق النائبة مثل التأخيرات والانتظار `0`، ويمكن للمعالجات تحديد قيمة موجبة أعلى عبر `config()` أو خصائص المهمة. ويمكن فقط لـ `cost_units` الخاص بتعريف الخطوة تعيين قيمة مقدارها `0`.

يفيد هذا عندما يمكن لسير العمل العودة إلى المنطقة نفسها أو التفرع إلى أعمال مكلفة بطرق لا يعكسها عدد الخطوات وحده. فقد يظل المخطِّط الذي يعيد تشغيل استدعاء مكلف للنموذج ضمن `max_transitions()`، ومع ذلك يتجاوز حدود التكلفة التي حددتها.

### `max_started_workflows()`

يحدّد هذا عدد مسارات العمل ذات المستوى الأعلى التي يمكن لتشغيل أن يبدأها عبر `start_workflows()` أو `start_agents()`. ويُتحقق من الحد قبل إرسال مسارات العمل الفرعية، لذا يفشل الأصل دون إنشاء مجموعة جزئية تتجاوز الميزانية المحددة.

عند تجاوز الميزانية، يفشل Queuety سير العمل فورًا بدلًا من إعادة محاولة الخطوة. ويُستثنى من ذلك ما يحدث عندما يُكمل `Queuety::signal()` انتظارًا، ويؤدي الانتقال الناتج إلى تجاوز الميزانية: عندئذ يُمرر الاستثناء إلى مستدعي `signal()`، ويُتراجع عن إدراج الإشارة، ويواصل سير العمل الانتظار.

## مراقبة ضوابط الحماية

تكشف حالة سير العمل عن:

- `definition_version`
- `definition_hash`
- `idempotency_key`
- `budget`

تتضمن حمولة `budget` الحدود المضبوطة والاستخدام الحالي، بما في ذلك حجم الحالة العامة الحالية بالبايت.

مثال:

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

$state->definition_version; // 'research.v2'
$state->definition_hash;    // '4c7a...'
$state->idempotency_key;    // 'brief:42:research'
$state->budget;             // [ 'max_transitions' => 20, ... ]
```
