
# アクショントリガー

`Queuety::on_action()`を使うと、通常のWordPressアクションを耐久性のあるワークフローのディスパッチに変えられます。

これにより、次のようにスムーズにつなげられます。

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

注目するイベントがすでにWordPressにあり、時間やコストのかかる処理を非同期で実行したい場合に便利です。

## 例：投稿の保存時にコンテンツをレビューする

```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}",
);
```

この例では、次のようになっています。

- `save_post`は元のWordPressイベントのままです
- `map`はフックの引数を通常のワークフロー状態に変換します
- `when`はキューに入れる前に不要なイベントを除外します
- `idempotency_key`はフックが繰り返し呼び出されても重複実行をディスパッチしないようにします

## 同期的に実行される処理

アクションのコールバック自体は、現在のWordPressリクエスト内で引き続き実行されます。

つまり、次の処理は同期的に実行されます。

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

ディスパッチ後に非同期で実行されるのはワークフローのステップだけです。

## ペイロードのルール

マッピングしたペイロードには、通常の配列、スカラー値、`null`を含めてください。

WordPress のような未加工のオブジェクトを、そのまま `WP_Post` のようにワークフローの状態へ渡さないでください。まず `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,
    ],
);
```

`_`で始まるキーは内部ワークフロー状態用に予約されているため、拒否されます。

## 受け付ける引数

WordPressでは、アクションコールバックの登録時に`accepted_args`の数が必要です。

Queuetyはデフォルトで`map`、`when`、`idempotency_key`の各コールバックからその数を推定するため、一般的なケースでは追加設定は不要です。

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

手動で上書きする場合は、`accepted_args`を明示的に渡します。

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

## インラインのワークフロービルダー

登録済みのワークフロー名またはインラインの`WorkflowBuilder`をディスパッチできます。

フック専用のワークフローを同じブートストラップファイルで定義する場合、インラインビルダーが便利です。

```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}",
);
```

## この方法が適している場面

次の場合はアクショントリガーを使います。

- 関連するイベントをWordPressがすでに発行している
- リクエストのタイムアウトやワーカーの再起動後も処理を継続したい
- 後続処理で分岐、待機、承認が必要になる可能性がある
- フックの重複呼び出しに対して耐久性のある冪等性が必要である

処理がWordPressイベントの境界に結びついていない場合は、代わりに`Queuety::dispatch()`または`Queuety::workflow()`を直接呼び出します。

## フィルターには使わない

`Queuety::on_action()`は意図的にアクション専用となっています。

フィルターはリクエスト処理時に同期的に行う変換です。通常は同期処理のままにしてください。WordPressでは、フィルター済みの値をすぐに返す必要があるためです。
