
# Handlingsudløsere

`Queuety::on_action()` lader dig gøre en almindelig WordPress-handling til en holdbar afsendelse af et workflow.

Det giver dig en enkel bro:

`WordPress action -> mapped payload -> durable workflow`

Dette er nyttigt, når den relevante hændelse allerede findes i WordPress, og det omkostningstunge eller langvarige svar skal køre asynkront.

## Eksempel: Gennemgå indhold, når et indlæg gemmes

```php
use Queuety\Queuety;

Queuety::on_action(
    'save_post',
    workflow: 'content_review',
    map: static fn ( int $post_id, object $post, bool $update ): array => [
        'post_id' => $post_id,
        'post_type' => $post->post_type,
        'update' => $update,
    ],
    when: static fn ( int $post_id, object $post ): bool => 'post' === $post->post_type,
    idempotency_key: static fn ( int $post_id ): string => "save_post:{$post_id}",
);
```

I dette eksempel:

- `save_post` er stadig den oprindelige WordPress-hændelse
- `map` omsætter rå hook-argumenter til almindelig workflowtilstand
- `when` springer uønskede hændelser over, før noget sættes i kø
- `idempotency_key` forhindrer gentagne hook-udløsninger i at sende dublerede kørsler videre

## Hvad kører synkront

Selve handlingscallbacken kører stadig i den aktuelle WordPress-anmodning.

Det betyder, at disse dele er synkrone:

- `when`
- `map`
- `idempotency_key`

Kun workflowtrinnene kører asynkront efter afsendelsen.

## Payloadregler

Tilpassede payloads bør indeholde almindelige arrays, skalarer og `null`.

Videregiv ikke rå WordPress-objekter som `WP_Post` direkte til workflowtilstanden. Normalisér dem først i `map()`:

```php
Queuety::on_action(
    'save_post',
    workflow: 'content_review',
    map: static fn ( int $post_id, object $post, bool $update ): array => [
        'post_id' => $post_id,
        'post_type' => $post->post_type,
        'post_status' => $post->post_status,
        'update' => $update,
    ],
);
```

Nøgler, der begynder med `_`, afvises, fordi disse navne er reserveret til intern workflowtilstand.

## Accepterede argumenter

WordPress kræver et antal `accepted_args`, når en handlingscallback registreres.

Queuety udleder det som standard fra dine `map`-, `when`- og `idempotency_key`-callbacks, så det almindelige tilfælde kræver ingen ekstra konfiguration:

```php
Queuety::on_action(
    'save_post',
    workflow: 'content_review',
    map: static fn ( int $post_id, object $post, bool $update ): array => [
        'post_id' => $post_id,
        'update' => $update,
    ],
);
```

Hvis du har brug for en manuel tilsidesættelse, skal du videregive `accepted_args` eksplicit:

```php
Queuety::on_action(
    'comment_post',
    workflow: 'comment_review',
    accepted_args: 2,
);
```

## Inline-workflowbyggere

Du kan sende et registreret workflow-navn eller en inline `WorkflowBuilder` videre.

Inline-byggere er nyttige, når det hookspecifikke workflow defineres i den samme bootstrap-fil:

```php
$review = Queuety::workflow( 'comment_review' )
    ->then( ModerateCommentStep::class )
    ->then( NotifyModeratorStep::class );

Queuety::on_action(
    'comment_post',
    workflow: $review,
    map: static fn ( int $comment_id ): array => [
        'comment_id' => $comment_id,
    ],
    idempotency_key: static fn ( int $comment_id ): string => "comment:{$comment_id}",
);
```

## Hvornår dette passer godt

Brug handlingsudløsere, når:

- WordPress allerede udsender den hændelse, du har brug for
- svaret skal kunne overleve anmodningstimeouts eller genstart af workerprocesser
- opfølgningsarbejdet kan forgrene sig, vente eller kræve godkendelse
- dublerede hook-udløsninger kræver holdbar idempotens

Brug i stedet et direkte `Queuety::dispatch()`- eller `Queuety::workflow()`-kald, når arbejdet ikke er knyttet til en WordPress-hændelsesgrænse.

## Ikke til filtre

`Queuety::on_action()` er bevidst begrænset til handlinger.

Filtre er synkrone transformationer, der udføres under anmodningen. De bør som regel forblive synkrone, fordi WordPress forventer, at en filtreret værdi returneres med det samme.
