
# الخطوات المتوازية

يمكن أحيانًا تشغيل عدة خطوات في الوقت نفسه. توزّع الطريقة `->parallel()` مجموعة من المعالجات للتنفيذ المتزامن. ولا يتقدم سير العمل إلا بعد اكتمال جميع المعالجات المتوازية.

## الطريقة `->parallel()`

```php
use Queuety\Queuety;

Queuety::workflow( 'enrich_profile' )
    ->then( FetchUserHandler::class )
    ->parallel( [
        FetchSocialProfileHandler::class,
        FetchPaymentHistoryHandler::class,
        FetchActivityLogHandler::class,
    ] )
    ->then( MergeAndSaveHandler::class )
    ->dispatch( [ 'user_id' => 42 ] );
```

في هذا المثال:
1. تعمل `FetchUserHandler` أولًا (بالتتابع)
2. تعمل ثلاثة معالجات بالتزامن (بالتوازي)
3. تعمل `MergeAndSaveHandler` بعد اكتمال المعالجات الثلاثة (بالتتابع)

## طريقة العمل

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

تُدمج القيمة التي يعيدها كل معالج متوازٍ في حالة سير العمل. وإذا أعادت عدة معالجات المفتاح نفسه، تسود نتيجة المعالج الذي يكتمل أخيرًا.

## دمج الحالة

يعيد كل معالج متوازٍ بيانات تُدمج في حالة سير العمل المشتركة:

```php
class FetchSocialProfileHandler implements Step {
    public function handle( array $state ): array {
        $profile = fetch_social_api( $state['user_id'] );
        return [ 'social_profile' => $profile ];
    }

    public function config(): array {
        return [];
    }
}

class FetchPaymentHistoryHandler implements Step {
    public function handle( array $state ): array {
        $payments = fetch_payment_api( $state['user_id'] );
        return [ 'payment_history' => $payments ];
    }

    public function config(): array {
        return [];
    }
}
```

بعد اكتمال الخطوة المتوازية، تحتوي الحالة على كل من `social_profile` و`payment_history`، ويمكن للخطوة المتتابعة التالية الوصول إليهما جميعًا.

## المزج بين التنفيذ المتتابع والمتوازي

يمكنك المزج بحرية بين استدعاءات `->then()` و`->parallel()`:

```php
Queuety::workflow( 'complex_pipeline' )
    ->then( SetupHandler::class )               // sequential
    ->parallel( [ TaskA::class, TaskB::class ] ) // parallel
    ->then( IntermediateHandler::class )         // sequential
    ->parallel( [ TaskC::class, TaskD::class ] ) // parallel
    ->then( FinalizeHandler::class )             // sequential
    ->dispatch( $payload );
```

## معالجة الأخطاء

إذا فشل أي معالج في مجموعة متوازية، يتبع سير العمل منطق إعادة المحاولة المعتاد لذلك المعالج. ولا تُعاد المعالجات المتوازية الأخرى التي اكتملت بالفعل. ويتابع سير العمل عند نجاح المعالج الفاشل. وإذا استنفد محاولات الإعادة ودُفنت مهمته، يُعلَّم سير العمل بأنه فاشل وتُدفن مهام الفروع المتبقية؛ استخدم `retry_workflow()` لإعادة تشغيل الخطوة الفاشلة.
