
# السلاسل المتتابعة

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

## طريقة `->then()`

استخدم `->then()` لإضافة خطوات متتابعة إلى سير عمل:

```php
use Queuety\Queuety;

Queuety::workflow( 'onboarding' )
    ->then( CreateAccountHandler::class )
    ->then( SendWelcomeEmailHandler::class )
    ->then( NotifyAdminHandler::class )
    ->dispatch( [ 'email' => 'user@example.com' ] );
```

تُنفّذ الخطوات بالترتيب الذي أُضيفت به. ولا يتقدم سير العمل إلا عند اكتمال الخطوة الحالية بنجاح.

## واجهة Step

تنفذ معالجات خطوات سير العمل واجهة `Queuety\Step`:

```php
use Queuety\Step;

class CreateAccountHandler implements Step {
    public function handle( array $state ): array {
        $user_id = wp_create_user( $state['email'], wp_generate_password() );
        return [ 'user_id' => $user_id ];
    }

    public function config(): array {
        return [
            'max_attempts' => 3,
        ];
    }
}
```

الفروق الرئيسية عن واجهة `Handler`:

| | `Handler` (المهام) | `Step` (عمليات سير العمل) |
|---|---|---|
| توقيع الطريقة | `handle(array $payload): void` | `handle(array $state): array` |
| الإدخال | حمولة المهمة | حالة سير العمل المتراكمة |
| الإخراج | لا شيء (void) | بيانات تُدمج في الحالة |

## تدفق الحالة

تتلقى كل خطوة الحالة المتراكمة كاملة وتعيد مصفوفة من أزواج المفاتيح والقيم الجديدة. تُدمج البيانات المعادة في الحالة لتستخدمها الخطوات التالية:

```php
class FetchUserHandler implements Step {
    public function handle( array $state ): array {
        // $state contains: ['user_id' => 42]
        $user = get_user_by( 'ID', $state['user_id'] );
        return [ 'user_name' => $user->display_name, 'user_email' => $user->user_email ];
    }

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

class GenerateReportHandler implements Step {
    public function handle( array $state ): array {
        // $state contains: ['user_id' => 42, 'user_name' => 'Alice', 'user_email' => 'alice@example.com']
        $report = build_report( $state['user_name'] );
        return [ 'report_url' => $report->url ];
    }

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

## إعداد الخطوة

تدعم طريقة `config()` المفاتيح التالية:

| المفتاح | النوع | القيمة الافتراضية | الوصف |
|---|---|---|---|
| `max_attempts` | `int` | `3` | الحد الأقصى لمحاولات إعادة تنفيذ هذه الخطوة |
| `backoff` | `string` | `exponential` | استراتيجية الانتظار بين محاولات الإعادة |

## مثال على مسار معالجة LLM

من حالات الاستخدام الشائعة تسلسل استدعاءات LLM API مع معالجة البيانات:

```php
use Queuety\Step;

class BuildPromptHandler implements Step {
    public function handle( array $state ): array {
        $user = get_user_by( 'ID', $state['user_id'] );
        $posts = get_posts( [ 'author' => $user->ID, 'numberposts' => 10 ] );
        $context = implode( "\n", array_map( fn( $p ) => $p->post_content, $posts ) );

        return [
            'prompt' => "Summarize this author's recent work:\n\n{$context}",
        ];
    }

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

class CallOpenAIHandler implements Step {
    public function handle( array $state ): array {
        $response = wp_remote_post( 'https://api.openai.com/v1/chat/completions', [
            'timeout' => 120,
            'headers' => [
                'Authorization' => 'Bearer ' . OPENAI_API_KEY,
                'Content-Type'  => 'application/json',
            ],
            'body' => json_encode( [
                'model'    => 'gpt-4',
                'messages' => [ [ 'role' => 'user', 'content' => $state['prompt'] ] ],
            ] ),
        ] );

        $body = json_decode( wp_remote_retrieve_body( $response ), true );
        return [ 'summary' => $body['choices'][0]['message']['content'] ];
    }

    public function config(): array {
        return [ 'max_attempts' => 5 ];
    }
}

class SaveSummaryHandler implements Step {
    public function handle( array $state ): array {
        $post_id = wp_insert_post( [
            'post_title'   => "Summary for user #{$state['user_id']}",
            'post_content' => $state['summary'],
            'post_status'  => 'publish',
        ] );
        return [ 'summary_post_id' => $post_id ];
    }

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

أطلق مسار المعالجة:

```php
Queuety::workflow( 'summarize_author' )
    ->then( BuildPromptHandler::class )
    ->then( CallOpenAIHandler::class )
    ->then( SaveSummaryHandler::class )
    ->on_queue( 'llm' )
    ->max_attempts( 5 )
    ->dispatch( [ 'user_id' => 42 ] );
```

إذا انتهت مهلة استدعاء OpenAI، يعيد العامل تنفيذ تلك الخطوة وحدها. وتكون المطالبة التي أُنشئت في الخطوة 0 محفوظة مسبقًا بأمان في حالة سير العمل.
