
# İş Akışı Sinyalleri

İş akışları, sinyalleri kullanarak duraklayabilir ve harici girdiyi bekleyebilir. `wait_for_signal()` ve `wait_for_signals()` oluşturucu yöntemleri, uygulamanız, bir operatör veya başka bir sistem `Queuety::signal()` aracılığıyla beklenen sinyali gönderene kadar iş akışını engelleyen adımlar ekler.

İnsan denetimli akışlar için Queuety ayrıca şunları içerir:

- ad alanlı bir onay yükü için `wait_for_approval()`
- yapılandırılmış insan girdisi için `wait_for_input()`
- açık onay/ret sonuçları için `wait_for_decision()`

Aracı çalıştırmalarını insan denetimi adımlarıyla birleştiren daha kapsamlı, baştan sona bir örnek için [Aracı Orkestrasyonu](https://queuety.inline0.dev/tr/docs/workflows/agent-orchestration) bölümüne bakın.

## `->wait_for_signal()` yöntemi

İş akışına bir sinyal bekleme adımı ekleyin:

```php
use Queuety\Queuety;

$workflow_id = Queuety::workflow( 'content_approval' )
    ->then( DraftContentHandler::class )
    ->wait_for_signal( 'approved' )
    ->then( PublishContentHandler::class )
    ->dispatch( [ 'post_id' => 99 ] );
```

İş akışı `wait_for_signal` adımına ulaştığında durumunu `waiting_for_signal` olarak ayarlar ve duraklar. Beklerken hiçbir iş çalışmaz ve kaynak tüketilmez.

Varsayılan olarak tek bir sinyal yükü, iş akışının üst düzey durumuyla birleştirilir. Yükün ad alanlı olmasını istiyorsanız bir `result_key` iletin:

```php
$workflow_id = Queuety::workflow( 'content_approval' )
    ->then( DraftContentHandler::class )
    ->wait_for_signal( 'approved', 'approval' )
    ->then( PublishContentHandler::class )
    ->dispatch( [ 'post_id' => 99 ] );
```

Sinyal geldikten sonra `$state['approval']`, sinyal yükü dizisini içerir.

## Birden çok sinyali bekleme

İş akışının birkaç olası sinyalden biriyle devam etmesi veya devam etmeden önce gereken tüm sinyalleri toplaması gerektiğinde `wait_for_signals()` kullanın.

```php
use Queuety\Enums\WaitMode;

$workflow_id = Queuety::workflow( 'moderation_gate' )
    ->then( SubmitForReviewHandler::class )
    ->wait_for_signals(
        [ 'editor_approved', 'legal_approved' ],
        WaitMode::All,
        'approvals'
    )
    ->then( PublishContentHandler::class )
    ->dispatch();
```

- `WaitMode::All`, yapılandırılan her sinyal kaydedilene kadar bekler.
- `WaitMode::Any`, yapılandırılan ilk sinyal gelir gelmez devam eder.

Bir `result_key` ile çoklu sinyal beklemesi, sinyal adına göre anahtarlanmış ilişkisel bir dizi saklar:

```php
[
    'editor_approved' => [ 'by' => 'editor@example.com' ],
    'legal_approved' => [ 'by' => 'legal@example.com' ],
]
```

Bir `result_key` olmadan eşleşen sinyal yükleri, adımın yapılandırıldığı sırayla üst düzey durumla birleştirilir.

## Eşleştirme ve ilişkilendirme

Sinyal beklemeleri, yük içeriğini eşleştirerek veya ortak bir anahtarla ilişkilendirerek ilgisiz olayları yok sayabilir.

```php
$workflow_id = Queuety::workflow( 'review_gate' )
    ->wait_for_signal(
        name: 'review_ready',
        result_key: 'review',
        match_payload: [ 'source' => 'editorial' ],
        correlation_key: 'task_id',
    )
    ->dispatch( [ 'task_id' => 'task-42' ] );
```

Bu örnekte bekleme yalnızca şu koşullarda devam eder:

- sinyal adı `review_ready` olur
- yük `source: editorial` içerir
- yükteki `task_id`, `$state['task_id']` ile eşleşir

Bu, birden çok harici sistem veya aracının aynı olay adlarını yayımladığı, ancak yalnızca tek bir yükün mevcut iş akışı çalıştırmasına ait olduğu durumlarda kullanışlıdır.

## İnsan onayı ve girdi yardımcıları

`wait_for_approval()` ve `wait_for_input()`, sinyal beklemeleri için kolaylık sağlayan sarmalayıcılardır. `wait_for_signal()` gibi çalışırlar, ancak varsayılan olarak ad alanlı bir sonuç anahtarı kullanırlar.

```php
$workflow_id = Queuety::workflow( 'blog_review' )
    ->then( GenerateDraftHandler::class )
    ->wait_for_approval()
    ->wait_for_input()
    ->then( HandleDecisionHandler::class )
    ->dispatch();
```

`approval` sinyalinden sonra `$state['approval']` onay yükünü içerir. `input` sinyalinden sonra `$state['input']` girdi yükünü içerir.

Onay veya ret geldiğinde tek bir adımın devam etmesini istiyorsanız `wait_for_decision()` kullanın:

```php
$workflow_id = Queuety::workflow( 'legal_review' )
    ->then( DraftContractHandler::class )
    ->wait_for_decision( result_key: 'review' )
    ->then( HandleReviewDecisionHandler::class )
    ->dispatch();
```

Sinyal geldikten sonra `$state['review']` şunları içerir:

```php
[
    'outcome' => 'approved', // or 'rejected'
    'signal'  => 'approved', // or 'rejected'
    'data'    => [ 'reviewer' => 'ops@example.com' ],
]
```

## Sinyal gönderme

`Queuety::signal()` kullanarak bir iş akışına sinyal gönderin:

```php
Queuety::signal( $workflow_id, 'approved' );
```

Sinyal, iş akışının beklediği sinyalle eşleştiğinde iş akışı devam eder ve sonraki adıma geçer.

İnsan denetimli akışlar için arayüz ayrıca anlamsal yardımcılar sunar:

```php
Queuety::approve_workflow( $workflow_id, [ 'reviewer' => 'editor@example.com' ] );
Queuety::reject_workflow( $workflow_id, [ 'reason' => 'needs citations' ] );
Queuety::submit_workflow_input( $workflow_id, [ 'notes' => 'Ship after copy edit' ] );
```

### Sinyal verileri

Sinyalle birlikte bir veri dizisi gönderebilirsiniz. Bu veriler iş akışı durumuyla birleştirilir ve sonraki adımlarda kullanılabilir:

```php
Queuety::signal( $workflow_id, 'approved', [
    'approved_by' => 'admin@example.com',
    'approved_at' => time(),
] );
```

Sonraki adımda:

```php
class PublishContentHandler implements Step {
    public function handle( array $state ): array {
        // $state['approved_by'] is 'admin@example.com'
        // $state['approved_at'] is the timestamp
        // $state['post_id'] is 99
        wp_update_post( [
            'ID'          => $state['post_id'],
            'post_status' => 'publish',
        ] );
        return [ 'published' => true ];
    }

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

`_` (alt çizgi) ile başlayan anahtarlar dahili kullanım için ayrılmıştır ve durumla birleştirilmez.

## Önceden var olan sinyaller

Sinyaller, iş akışı bekleme adımına ulaşmadan önce gönderilebilir. Bir sinyal geldiğinde, iş akışının geçerli durumundan bağımsız olarak `queuety_signals` tablosuna kaydedilir. İş akışı daha sonra `wait_for_signal` adımına ulaştığında önceden var olan sinyalleri kontrol eder ve varsa hemen devam eder.

Bu, sıranın önemli olmadığı anlamına gelir:

```php
// Dispatch workflow
$workflow_id = Queuety::workflow( 'order_fulfillment' )
    ->then( PrepareOrderHandler::class )
    ->wait_for_signal( 'payment_confirmed' )
    ->then( ShipOrderHandler::class )
    ->dispatch( [ 'order_id' => 123 ] );

// Signal arrives before the workflow reaches the wait step
Queuety::signal( $workflow_id, 'payment_confirmed', [ 'transaction_id' => 'txn_abc' ] );

// When the workflow finishes PrepareOrderHandler and reaches the wait step,
// it sees the pre-existing signal and continues immediately.
```

## Sinyal beklenirken iş akışının durumu

Sinyal beklenirken iş akışının durumu `WorkflowStatus::WaitingForSignal` (`waiting_for_signal`) olur:

```php
$state = Queuety::workflow_status( $workflow_id );
echo $state->status->value; // 'waiting_for_signal'
echo $state->wait_type;     // 'signal'
echo $state->wait_mode;     // 'all' or 'any'
print_r( $state->waiting_for ); // ['approved']
print_r( $state->wait_details ); // matched/remaining, correlation info, result key, ...
```

## Kullanım örneği: insan onayı

Bir insan inceleyenin içerik yayımlanmadan önce onay vermesi gereken bir onay iş akışı oluşturun:

```php
$workflow_id = Queuety::workflow( 'blog_review' )
    ->then( GenerateDraftHandler::class )
    ->then( NotifyReviewerHandler::class )
    ->wait_for_decision( result_key: 'review' )
    ->then( HandleDecisionHandler::class )
    ->dispatch( [ 'topic' => 'PHP middleware patterns' ] );
```

`NotifyReviewerHandler`, onaylama/reddetme bağlantıları içeren bir e-posta veya Slack mesajı gönderir. Bu bağlantılar, sinyal gönderen denetleyicinizi çağırır:

```php
// In your approval controller
Queuety::approve_workflow(
    $workflow_id,
    [
        'reviewer'    => $current_user->user_email,
        'reviewed_at' => time(),
    ],
    'approved'
);
```

`HandleDecisionHandler` adımı `$state['review']['outcome']` değerini okur ve taslağı yayımlar veya arşivler.

## Kullanım örneği: harici API geri çağrısı

Harici bir hizmetten webhook bekleyin:

```php
$workflow_id = Queuety::workflow( 'generate_video' )
    ->then( SubmitToRenderServiceHandler::class )
    ->wait_for_signal( 'render_complete' )
    ->then( DownloadVideoHandler::class )
    ->then( NotifyUserHandler::class )
    ->dispatch( [ 'template_id' => 'promo_v2', 'user_id' => 42 ] );
```

Harici hizmet webhook uç noktanıza istek gönderdiğinde:

```php
// In your webhook handler
$payload = json_decode( file_get_contents( 'php://input' ), true );
$workflow_id = (int) $payload['metadata']['workflow_id'];

Queuety::signal( $workflow_id, 'render_complete', [
    'video_url'  => $payload['output_url'],
    'duration'   => $payload['duration_seconds'],
] );
```

## Tek iş akışında birden çok sinyal kapısı

Bir iş akışı birden çok noktada sinyal bekleyebilir:

```php
Queuety::workflow( 'multi_approval' )
    ->then( CreateProposalHandler::class )
    ->wait_for_signal( 'manager_approval' )
    ->then( EscalateToDirectorHandler::class )
    ->wait_for_signal( 'director_approval' )
    ->then( ExecuteProposalHandler::class )
    ->dispatch( [ 'proposal_id' => 7 ] );
```

Her sinyal bekleme adımı bağımsızdır. Aynı iş akışında `wait_for_signal()`, `wait_for_signals()`, `wait_for_approval()`, `wait_for_input()` ve `wait_for_decision()` öğelerini birlikte kullanabilirsiniz.
