
# العمال

العمال عمليات طويلة التشغيل تستعلم من قاعدة البيانات عن الوظائف المعلّقة، وتنفذها، وتتقدم في تدفقات العمل. يعمل الأمر `wp queuety work` داخل WP-CLI، بينما تُحجز الوظائف من قائمة الانتظار مباشرةً من MySQL باستخدام أفضل برنامج تشغيل DB متاح لـQueuety.

تثبت الإضافة أيضًا بديل WordPress cron افتراضيًا يعمل مرة كل دقيقة للبيئات التي لا تتيح الوصول إلى الصدفة. تغطي هذه الصفحة عمال WP-CLI المخصصين، وهم نمط النشر الموصى به لزيادة معدل الإنجاز.

## بدء عامل

```bash
wp queuety work
```

يبدأ هذا عاملًا واحدًا على قائمة الانتظار `default`. ويعمل في حلقة: يحجز وظيفة، وينفذها، ثم يكرر. عندما تكون قائمة الانتظار فارغة، ينتظر `QUEUETY_WORKER_SLEEP` ثانية (الافتراضي: 1) قبل الاستعلام مجددًا.

### الخيارات

| الخيار | الوصف |
|---|---|
| `--queue=<queue>` | Queue(s) للمعالجة، مفصولة بفواصل لترتيب الأولوية (الافتراضي: `default`) |
| `--once` | معالجة مهمة واحدة كحد أقصى ثم الخروج |
| `--workers=<n>` | إنشاء N من عمليات العاملين (يتطلب الامتدادين `pcntl` و`posix`) |
| `--min-workers=<n>` | الحد الأدنى لعدد العاملين في مجموعة متكيفة. يتطلب `--max-workers` |
| `--max-workers=<n>` | الحد الأقصى لعدد العاملين في مجموعة متكيفة |

```bash
# Process a specific queue
wp queuety work --queue=emails

# Process at most one job and exit
wp queuety work --once

# Run 4 concurrent workers
wp queuety work --workers=4

# Scale between 2 and 6 workers as backlog changes
wp queuety work --queue=providers --min-workers=2 --max-workers=6
```

## أولويات قوائم الانتظار المتعددة

يمكن لعامل واحد معالجة قوائم انتظار متعددة حسب ترتيب الأولوية. مرر قائمة مفصولة بفواصل لأسماء قوائم الانتظار إلى `--queue`:

```bash
wp queuety work --queue=critical,default,low
```

يحاول العامل حجز وظيفة من كل قائمة انتظار حسب الترتيب المذكور. يفحص `critical` أولًا. إذا احتوت `critical` على وظيفة، يعالجها. وإذا كانت `critical` فارغة، ينتقل إلى `default`، ثم إلى `low`. وهذا يعني أن قوائم الانتظار الأعلى أولوية تُفرغ دائمًا قبل الأقل أولوية.

### آلية ترتيب الأولويات

في كل دورة، يحاول العامل الحجز من قائمة الانتظار الأولى في القائمة. إذا كانت فارغة أو متوقفة مؤقتًا، ينتقل إلى التالية، ويواصل ذلك حتى يعثر على وظيفة أو يفحص القائمة بأكملها. إذا لم يعثر على وظيفة، ينتظر العامل ثم يعيد المحاولة. هذا نموذج أولوية صارم، ما يعني أن التدفق المستمر لوظائف `critical` سيحرم `default` و`low` من الخدمة. إذا كانت قوائم الانتظار الأقل أولوية بحاجة إلى معدل إنجاز مضمون، فاستخدم عمالًا مخصصين لها.

### استخدام قوائم الانتظار المتعددة في PHP

تقبل الطريقتان `Worker::run()` و`Worker::flush()` سلسلة أو مصفوفة:

```php
// Comma-separated string
Queuety::worker()->run( 'critical,default,low' );

// Array
Queuety::worker()->run( [ 'critical', 'default', 'low' ] );

// flush() also supports multi-queue
$count = Queuety::worker()->flush( 'critical,default,low' );
```

### استراتيجيات النشر

**يمنحك تخصيص عمال لكل قائمة انتظار** تحكمًا كاملًا في التزامن والعزل. تحصل كل قائمة انتظار على process(es) خاص بها، ولا يمكن أن تحرمها قوائم الانتظار الأخرى من الخدمة:

```ini
[program:queuety-critical]
command=wp queuety work --queue=critical
numprocs=4

[program:queuety-default]
command=wp queuety work --queue=default
numprocs=2

[program:queuety-low]
command=wp queuety work --queue=low
numprocs=1
```

**ترتيب الأولوية باستخدام عامل واحد** أسهل في الإدارة، ويعمل جيدًا عندما تستطيع قوائم الانتظار الأقل أولوية تحمل التأخير:

```ini
[program:queuety-worker]
command=wp queuety work --queue=critical,default,low
numprocs=2
```

يمكنك أيضًا الجمع بين النهجين: عمال مخصصون لـ`critical` لضمان معدل الإنجاز، وعامل مرتب حسب الأولوية لبقية المهام:

```ini
[program:queuety-critical]
command=wp queuety work --queue=critical
numprocs=2

[program:queuety-fallback]
command=wp queuety work --queue=default,low
numprocs=2
```

## القبول المراعي للموارد

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

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

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

تُستخدم سجلات التنفيذ الأخيرة أيضًا لإنشاء ملف قبول مبسط. عند تفعيل قبول الموارد، يفحص Queuety متوسط المدة الأخير وذروة الذاكرة للمعالج الذي يستعد لتشغيله. إذا كان العامل الحالي قريبًا بالفعل من حد الذاكرة المضبوط له، أو بلغت مجموعة الطابور أو المزود ميزانيتها الموزونة، أو بدا أن الحاوية الحالية لا تملك ذاكرة متبقية كافية للملف المرصود لذلك المعالج، أو كانت عملية من نمط `--once` قريبة من بلوغ حدها الزمني، يؤجل Queuety المهمة بدلًا من بدء عمل يُرجح ألا يكتمل بسلاسة.

يمكنك تفعيل السياسة من تعريف العمل بدلًا من أمر العامل:

```php
class CallProviderStep implements \Queuety\Step {
    public function handle( array $state ): array {
        // ...
    }

    public function config(): array {
        return [
            'concurrency_group' => 'providers',
            'concurrency_limit' => 3,
            'cost_units' => 5,
        ];
    }
}
```

يمكن إرفاق البيانات الوصفية نفسها بفئات المهام القابلة للإرسال عبر الخصائص العامة، أو بإرسال فردي من خلال `PendingJob::concurrency_group()` و`PendingJob::cost_units()`.

يمكن التحكم بملف القبول على جانب العامل باستخدام هذه الثوابت:

| الثابت | الوصف |
|---|---|
| `QUEUETY_RESOURCE_ADMISSION` | تفعيل فحوصات القبول المستندة إلى الملف أو تعطيلها |
| `QUEUETY_RESOURCE_PROFILE_WINDOW_MINUTES` | المدة التي يرجع إليها عند إنشاء ملفات المعالجات الأخيرة |
| `QUEUETY_RESOURCE_PROFILE_TTL` | مدة صلاحية ذاكرة التخزين المؤقت لملفات المعالجات الأخيرة |
| `QUEUETY_RESOURCE_MEMORY_HEADROOM_MB` | هامش الذاكرة المحجوز قبل قبول مهمة أخرى |
| `QUEUETY_RESOURCE_SYSTEM_MEMORY_AWARENESS` | تفعيل فحوصات ذاكرة الحاوية أو المضيف بأفضل جهد أو تعطيلها |
| `QUEUETY_RESOURCE_SYSTEM_MEMORY_HEADROOM_MB` | هامش ذاكرة النظام المحجوز قبل قبول مهمة أخرى |
| `QUEUETY_RESOURCE_QUEUE_COST_BUDGETS` | ميزانيات التكلفة الموزونة، مفهرسة باسم الطابور |
| `QUEUETY_RESOURCE_GROUP_COST_BUDGETS` | ميزانيات التكلفة الموزونة، مفهرسة حسب `concurrency_group` |
| `QUEUETY_RESOURCE_TIME_HEADROOM_MS` | هامش الوقت المحجوز لعمليات العامل التي تُشغّل مرة واحدة |

## دورة حياة العامل

يتوقف العامل بسلاسة بعد إكمال مهمته الحالية عند تحقق أي من الشروط التالية:

| الشرط | الإعداد |
|---|---|
| أقصى عدد من المهام التي تمت معالجتها | `QUEUETY_WORKER_MAX_JOBS` (الافتراضي: 1000) |
| تجاوز الحد الأقصى للذاكرة | `QUEUETY_WORKER_MAX_MEMORY` (الافتراضي: 128 MB) |

بعد التوقف، يخرج العامل بشكل سليم. في بيئة الإنتاج، يعيد مدير العمليات تشغيله تلقائيًا.

لم تُعالج الإشارات بسلاسة بعد ([#4](https://github.com/inline0/queuety/issues/4)). لا تثبّت عملية `wp queuety work` منفردة أي معالج للإشارات، لذا ينهيها `SIGTERM` أو `SIGINT` (Ctrl+C) فورًا، حتى لو كان ذلك في منتصف مهمة. تظل المهمة في حالة `processing` إلى أن تعيدها آلية استرداد المهام القديمة ضبطها بعد `QUEUETY_STALE_TIMEOUT` ثانية، لذا احرص على أن تكون المعالجات آمنة لإعادة المحاولة. تمرر مجموعة العمال `SIGTERM` إلى العمليات التابعة، لكن العمليات التابعة لا تتصرف استجابةً لها، لذلك تواصل المجموعة العمل حتى تتوقف لأحد الأسباب المذكورة أعلاه. عند الحاجة إلى إيقاف مجموعة، اضبط مهلة إيقاف في مدير العمليات، وبعدها يرسل `SIGKILL`.

## التزامن بين عدة عمال

تُنشئ العلامة `--workers=N` عدد N من العمليات التابعة باستخدام `pcntl_fork()`. ينشئ كل تابع اتصالًا خاصًا بقاعدة البيانات ويعالج المهام بصورة مستقلة. تراقب العملية الأم العمليات التابعة وتعيد تشغيل أي عملية تتعطل.

```bash
wp queuety work --queue=default --workers=4
```

المتطلبات:
يجب تثبيت الإضافتين `pcntl` و`posix` PHP (من دون `pcntl` سيفشل الأمر برسالة "pcntl extension is required for --workers=N.")، ويستخدم كل تابع اتصالًا خاصًا بقاعدة البيانات، لذا يجب أن يستوعب إعداد MySQL `max_connections` مجموعة العمال. تنطبق المتطلبات نفسها على مجموعات العمال التكيفية (`--min-workers`/`--max-workers`).

## مجموعات العمال التكيفية

تحافظ المجموعات التكيفية على عدد أدنى من العمال الجاهزين، ثم تزيد العدد أو تقلّصه ضمن نطاق مضبوط:

```bash
wp queuety work --queue=providers --min-workers=2 --max-workers=6
```

تراقب العملية الأم الأعمال المتراكمة القابلة للمطالبة بها في مجموعة الطوابير المحددة، وتضبط عدد العمليات التابعة بما يتناسب مع هذا التراكم، ضمن الحد الأقصى المضبوط. عندما يهدأ الطابور، تنتظر المجموعة مدة السماح بالخمول قبل تقليص العدد، كي لا تؤدي الارتفاعات القصيرة إلى تغييرات متكررة وفورية في قائمة العمليات.

تظل زيادة العدد متحفظة. عندما يستطيع Queuety قراءة بيانات قياس الذاكرة للحاوية أو المضيف، يمتنع عن إضافة مزيد من العمليات التابعة إن لم تتوفر ذاكرة متبقية كافية لموارد عامل كامل.

يمكن التحكم بحلقة التوسّع على جانب العملية الأم باستخدام:

| الثابت | الوصف |
|---|---|
| `QUEUETY_WORKER_POOL_SCALE_INTERVAL` | معدل تكرار مواءمة العملية الأم لحجم المجموعة |
| `QUEUETY_WORKER_POOL_IDLE_GRACE` | مدة هدوء الأعمال المتراكمة المطلوبة قبل تقليص العدد |

## استرداد المهام القديمة

إذا تعطّل عامل أثناء معالجة مهمة، تبقى المهمة في حالة `processing`. يتحقق العامل طويل التشغيل مرة كل دقيقة تقريبًا من وجود مهام بقيت في حالة `processing` مدة تتجاوز `QUEUETY_STALE_TIMEOUT` ثانية. تُعاد محاولة المهمة القديمة التي لا تزال لها محاولات متبقية بعد مهلة التراجع؛ أما التي استنفدت كل محاولاتها فتُدفن، ويُعلَّم سير عملها بأنه فاشل. لا تجري عمال `--once` ولا آلية WP-Cron الاحتياطية هذا الفحص.

استرداد المهام القديمة يدويًا:

```bash
wp queuety recover
```

## وضع التفريغ

عالج جميع المهام المعلّقة ثم اخرج. مفيد للاختبار أو لمعالجة دفعة لمرة واحدة:

```bash
wp queuety flush
wp queuety flush --queue=emails
```

## النشر في بيئة الإنتاج

في بيئة الإنتاج، استخدم مدير عمليات لإبقاء العمال قيد التشغيل. إليك طريقتان شائعتان.

### Supervisord

```ini
[program:queuety-default]
command=wp queuety work --queue=default
directory=/var/www/html
autostart=true
autorestart=true
numprocs=2
process_name=%(program_name)s_%(process_num)02d
stdout_logfile=/var/log/queuety-default.log
stderr_logfile=/var/log/queuety-default-error.log

[program:queuety-emails]
command=wp queuety work --queue=emails
directory=/var/www/html
autostart=true
autorestart=true
numprocs=1
stdout_logfile=/var/log/queuety-emails.log
stderr_logfile=/var/log/queuety-emails-error.log
```

### Systemd

```ini
[Unit]
Description=Queuety Worker (default queue)
After=mysql.service

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/html
ExecStart=/usr/local/bin/wp queuety work --queue=default
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```

التفعيل وبدء التشغيل:

```bash
sudo systemctl enable queuety-worker
sudo systemctl start queuety-worker
```

### نصائح النشر

شغّل عمالًا منفصلين لطوابير منفصلة عندما تحتاج إلى عزل أقوى. استخدم `--workers=N` عندما يكون عبء العمل كثيفًا بالمعالجة، وفضّل العمال الذين يشرف عليهم النظام كلٌّ على حدة عندما يكون عبء العمل معظمه عمليات إدخال وإخراج. اضبط `QUEUETY_WORKER_MAX_JOBS` إذا أردت عمليات إعادة تشغيل دورية لتحرير الذاكرة، وتابع عدد `buried` عبر [خطافات الويب](https://queuety.inline0.dev/ar/docs/features/webhooks) أو [المقاييس](https://queuety.inline0.dev/ar/docs/features/metrics).
