مسارات العمل
تقسم مسارات العمل المهام طويلة التشغيل إلى خطوات منفصلة. تحفظ كل خطوة ناتجها في مخزن حالة مشترك في قاعدة البيانات. إذا تعطل PHP في منتصف خطوة، يعيد العامل محاولة تلك الخطوة مع بقاء الحالة السابقة كاملة.
ما مسارات العمل؟
مسار العمل سلسلة مرتبة من الخطوات. كل خطوة هي فئة PHP تتلقى الحالة المتراكمة من جميع الخطوات السابقة، وتعيد بيانات جديدة لدمجها في الحالة. يتقدم سير العمل خطوة واحدة في كل مرة، مع إحاطة كل انتقال بمعاملة MySQL ذرية.
use Queuety\Queuety;
$workflow_id = Queuety::workflow( 'generate_report' )
->then( FetchDataHandler::class )
->then( CallLLMHandler::class )
->then( FormatOutputHandler::class )
->dispatch( [ 'user_id' => 42 ] );
تراكم الحالة
تصبح الحمولة الأولية التي تمررها إلى dispatch() هي الحالة المبدئية. وتُدمج المفاتيح التي تعيدها كل خطوة في الحالة. المفاتيح التي تبدأ بـ _ محجوزة لقيم التحكم مثل _next_step، ولا تُدمج في الحالة العامة:
dispatch(['user_id' => 42])
Step 0: FetchDataHandler -> returns ['user_name' => 'Alice']
state: {user_id: 42, user_name: 'Alice'}
Step 1: CallLLMHandler -> returns ['llm_response' => '...']
state: {user_id: 42, user_name: 'Alice', llm_response: '...'}
Step 2: FormatOutputHandler -> returns ['report_url' => '/reports/42.pdf']
state: {user_id: 42, user_name: 'Alice', llm_response: '...', report_url: '/reports/42.pdf'}
ترى كل خطوة الحالة المتراكمة كاملة. وهذا يسهّل تمرير البيانات بين الخطوات دون أي تخزين خارجي.
إمكانية الاستئناف
تستمر مسارات العمل لأنها تحفظ الحالة في قاعدة البيانات بعد كل خطوة. إذا تعطل العامل أثناء الخطوة 1، يُعاد تشغيل سير العمل من الخطوة 1 مع بقاء ناتج الخطوة 0 في الحالة.
حد الخطوة معاملة MySQL واحدة تنفذ ذريًا ما يلي:
- تحديث حالة سير العمل بناتج الخطوة
- وضع علامة الاكتمال على مهمة الخطوة الحالية
- إدراج مهمة الخطوة التالية في قائمة الانتظار
يضمن هذا عدم فقدان أي حالة، حتى عند وقوع أعطال أو انتهاء المهلة أو أخطاء PHP الجسيمة.
دورة حياة سير العمل
dispatch() -> running -> step 0 -> step 1 -> ... -> step N -> completed
| |
| +-> failed -> retry -> running (from failed step)
|
+-> paused -> resumed -> running
|
+-> waiting_for_signal -> signal received -> running
|
+-> waiting_for_workflows -> dependency settles -> running
|
+-> cancelled (via cancel_workflow)
| الحالة | الوصف |
|---|---|
running |
معالجة الخطوات بنشاط |
completed |
اكتملت جميع الخطوات بنجاح |
failed |
فشلت خطوة بعد استنفاد محاولات الإعادة |
paused |
أُوقف مؤقتًا يدويًا. قد يكتمل العمل الجاري، لكن لن تُدرج الخطوات اللاحقة في قائمة الانتظار حتى استئنافه |
waiting_for_signal |
في انتظار إشارة خارجية عبر Queuety::signal() |
waiting_for_workflows |
في انتظار اكتمال سير عمل آخر أو أكثر عبر wait_for_workflow() أو wait_for_workflows() |
cancelled |
أُلغي صراحةً عبر Queuety::cancel_workflow(). تُدفن المهام المعلقة ويُشغّل معالج تنظيف اختياري. |
إدارة مسارات العمل
تحقق من الحالة:
$state = Queuety::workflow_status( $workflow_id );
echo $state->status->value; // 'running'
echo $state->current_step; // 1
echo $state->total_steps; // 3
print_r( $state->waiting_for ); // ['42'] while waiting on another workflow
print_r( $state->wait_details ); // matched/remaining blockers, result key, correlation info
الإيقاف المؤقت والاستئناف:
Queuety::pause_workflow( $workflow_id );
Queuety::resume_workflow( $workflow_id );
أعد محاولة سير عمل فاشل بدءًا من الخطوة التي فشلت:
Queuety::retry_workflow( $workflow_id );
ألغِ سير عمل وشغّل معالجات التنظيف:
Queuety::cancel_workflow( $workflow_id );
راجع الإلغاء للاطلاع على تفاصيل معالجات التنظيف وما يحدث عند إلغاء سير عمل.
خيارات سير العمل
عيّن قائمة الانتظار والأولوية وسلوك إعادة المحاولة لجميع خطوات سير العمل:
use Queuety\Enums\Priority;
Queuety::workflow( 'important_pipeline' )
->on_queue( 'pipelines' )
->with_priority( Priority::High )
->max_attempts( 5 )
->on_cancel( PipelineCleanupHandler::class )
->prune_state_after( 3 )
->then( StepA::class )
->then( StepB::class )
->dispatch( $payload );
تسجل الطريقة on_cancel() معالج تنظيف يُشغّل عند إلغاء سير العمل. راجع الإلغاء.
تتيح الطريقة prune_state_after() الإزالة التلقائية لنواتج الخطوات القديمة لإبقاء حالة سير العمل محدودة الحجم. راجع تنقية الحالة.
استخدم compensate_with() لإرفاق معالج تعويض بكل خطوة. واستخدم compensate_on_failure() عندما تريد تشغيل تعويضات الخطوات المكتملة تلقائيًا بعد فشل سير العمل، وليس عند الإلغاء الصريح فقط. راجع التعويض.
استخدم ضوابط حماية سير العمل عند الحاجة إلى تنسيق أكثر أمانًا للعمليات طويلة الأمد: تضع version() وسم إصدار على مستوى التطبيق لتعريف، كما يخزن Queuety تجزئة حتمية للتعريف لكل تشغيل، ويجعل idempotency_key() الإرسال مستدامًا عبر المحاولات المتكررة أو الطلبات المكررة، بينما تُفشل max_transitions() وmax_for_each_items() وmax_state_bytes() عمليات التشغيل الجامحة قبل أن تتفاقم. راجع ضوابط الحماية.
أنواع الخطوات
يدعم Queuety أحد عشر نوعًا من الخطوات ضمن سير العمل:
- السلاسل المتتابعة باستخدام
->then()للتنفيذ خطوة تلو الأخرى - المجموعات المتوازية باستخدام
->parallel()للتنفيذ المتزامن - التكرار الديناميكي لكل عنصر باستخدام
->for_each()لأعمال الفروع المكتشفة أثناء التشغيل ودلالات الاكتمال الصريحة - عمليات التسليم غير المتزامنة باستخدام
->start_workflows()أو->start_agents()لإرسال مسارات عمل فرعية مستقلة من العناصر المكتشفة أثناء التشغيل - التفرع الشرطي باستخدام خطوات مسماة و
_next_step - التكرارات باستخدام
->repeat_until()و->repeat_while()للعودة المستدامة إلى خطوات سابقة مسماة - تشغيل مسارات العمل باستخدام
->run_workflow()للتكوين المتداخل - التأخيرات المستدامة باستخدام
->delay()للتأخير المحدد بالوقت - الإشارات باستخدام
->wait_for_signal()و->wait_for_signals()و->wait_for_approval()و->wait_for_input()و->wait_for_decision()لتشغيل الأحداث الخارجية - تبعيات مسارات العمل باستخدام
->wait_for_workflow()و->wait_for_workflows()و->wait_for_agents()للتنسيق بين مسارات العمل - خطوات البث باستخدام الواجهة
StreamingStepلإخراج مستدام قائم على أجزاء
أنماط شائعة
إذا كنت تبني أنظمة مستقلة أو شبه مستقلة، فابدأ بـ تنسيق الوكلاء. يوضح كيف تتكامل for_each() وstart_agents() وwait_for_agents() وwait_for_workflow() وwait_for_decision() في تدفقات عمل المخطِّط والمنفّذ ومراجعة البشر الفعلية.