
# Munkafolyamatjelek

A munkafolyamatok jelek segítségével szüneteltethetők, és külső bemenetre várhatnak. A `wait_for_signal()` és `wait_for_signals()` összeállítómetódusok olyan lépéseket iktatnak be, amelyek addig blokkolják a munkafolyamatot, amíg az alkalmazás, egy operátor vagy egy másik rendszer el nem küldi a várt jelet a `Queuety::signal()` segítségével.

Az emberi közreműködést igénylő folyamatokhoz a Queuety a következőket is tartalmazza:

- `wait_for_approval()` névtérrel ellátott jóváhagyási adatcsomaghoz
- `wait_for_input()` strukturált emberi bemenethez
- `wait_for_decision()` kifejezett jóváhagyási/elutasítási eredményekhez

Az ügynökfuttatásokat emberi ellenőrzési pontokkal ötvöző, átfogó példát az [Ügynökök vezénylése](https://queuety.inline0.dev/hu/docs/workflows/agent-orchestration) oldalon talál.

## A `->wait_for_signal()` metódus

Jelre váró lépés hozzáadása a munkafolyamathoz:

```php
use Queuety\Queuety;

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

Amikor a munkafolyamat eléri a `wait_for_signal` lépést, állapota `waiting_for_signal` lesz, és szünetel. Várakozás közben nem futnak feladatok, és nem fogyaszt erőforrásokat.

Alapértelmezés szerint egyetlen jel adatcsomagja egyesül a munkafolyamat legfelső szintű állapotával. Ha inkább névtérrel ellátva szeretné tárolni az adatcsomagot, adjon át egy `result_key` értéket:

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

A jel érkezése után a `$state['approval']` a jel adatcsomagjainak tömbjét tartalmazza.

## Várakozás több jelre

Használja a `wait_for_signals()` lehetőséget, ha a munkafolyamatnak több lehetséges jel bármelyikére fel kell oldódnia, vagy ha a folytatás előtt össze kell gyűjtenie az összes szükséges jelet.

```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();
```

- A `WaitMode::All` megvárja, amíg minden beállított jel rögzítésre kerül.
- A `WaitMode::Any` folytatódik, amint megérkezik az első beállított jel.

A `result_key` használatakor a több jelre váró lépés a jelek neve szerint kulcsolt asszociatív tömböt tárol:

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

A `result_key` nélkül a hozzá illeszkedő jelek adatcsomagjai a lépések beállítási sorrendjében egyesülnek a legfelső szintű állapottal.

## Egyezés és korreláció

A jelre váró lépések figyelmen kívül hagyhatják a nem kapcsolódó eseményeket az adatcsomag tartalmának ellenőrzésével vagy egy közös kulcs szerinti korrelációval.

```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' ] );
```

Ebben a példában a várakozás csak akkor folytatódik, ha:

- a jel neve `review_ready`
- az adatcsomag tartalmazza a `source: editorial` értéket
- az adatcsomag `task_id` értéke megegyezik a `$state['task_id']` értékével

Ez akkor hasznos, ha több külső rendszer vagy ügynök tesz közzé azonos nevű eseményeket, de csak egy adatcsomag tartozik az aktuális munkafolyamat-futáshoz.

## Emberi jóváhagyási és adatbeviteli segédmetódusok

A `wait_for_approval()` és a `wait_for_input()` kényelmi burkoló a jelre váró lépések körül. Úgy működnek, mint a `wait_for_signal()`, de alapértelmezés szerint névtérrel ellátott eredménykulcsot használnak.

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

A `approval` jel után a `$state['approval']` tartalmazza a jóváhagyási adatcsomagot. A `input` jel után a `$state['input']` tartalmazza a beviteli adatcsomagot.

Használja a `wait_for_decision()` lehetőséget, ha azt szeretné, hogy egyetlen lépés jóváhagyásra vagy elutasításra is folytatódjon:

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

A jel érkezése után a `$state['review']` a következőket tartalmazza:

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

## Jel küldése

Jel küldése egy munkafolyamatnak a `Queuety::signal()` használatával:

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

Amikor a jel megegyezik azzal, amelyre a munkafolyamat vár, a munkafolyamat folytatódik, és továbblép a következő lépésre.

Az emberi közreműködést igénylő folyamatokhoz a homlokzati réteg szemantikus segédmetódusokat is kínál:

```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' ] );
```

### Jeladatok

A jellel együtt átadhat egy adattömböt. Az adatok egyesülnek a munkafolyamat állapotával, így a későbbi lépések számára is elérhetők:

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

A következő lépésben:

```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 [];
    }
}
```

A `_` (aláhúzásjel) karakterrel kezdődő kulcsok belső használatra vannak fenntartva, és nem kerülnek be az állapotba.

## Korábban érkezett jelek

A jelek még azelőtt elküldhetők, hogy a munkafolyamat elérné a várakozó lépést. A jel érkezésekor a `queuety_signals` táblában kerül rögzítésre, a munkafolyamat aktuális állapotától függetlenül. Amikor a munkafolyamat később eléri a `wait_for_signal` lépést, ellenőrzi, érkezett-e már jel, és találat esetén azonnal folytatódik.

Ez azt jelenti, hogy a sorrend nem számít:

```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.
```

## A munkafolyamat állapota jelre várás közben

Jelre várakozás közben a munkafolyamat állapota `WorkflowStatus::WaitingForSignal` (`waiting_for_signal`):

```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, ...
```

## Használati eset: emberi jóváhagyás

Hozzon létre jóváhagyási munkafolyamatot, amelyben egy emberi ellenőrnek jóvá kell hagynia a tartalmat, mielőtt az élesbe kerül:

```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' ] );
```

A `NotifyReviewerHandler` e-mailt vagy Slack üzenetet küld jóváhagyási/elutasítási hivatkozásokkal. Ezek a hivatkozások meghívják a vezérlőt, amely elküldi a jelet:

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

A `HandleDecisionHandler` lépés beolvassa a `$state['review']['outcome']` értékét, majd közzéteszi vagy archiválja a piszkozatot.

## Használati eset: külső API visszahívás

Várjon egy külső szolgáltatás webhookjára:

```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 ] );
```

Amikor a külső szolgáltatás adatot küld a webhook-végpontjára:

```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'],
] );
```

## Több jelkapu egy munkafolyamatban

A munkafolyamat több ponton is várhat jelekre:

```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 ] );
```

Minden jelre váró lépés önálló. Ugyanabban a munkafolyamatban vegyesen használhatja a következőket: `wait_for_signal()`, `wait_for_signals()`, `wait_for_approval()`, `wait_for_input()` és `wait_for_decision()`.
