
# PHP API

Queuetyのすべての機能は、`Queuety\Queuety`静的クラスから利用できます。ジョブのディスパッチ、ワークフローの構築、ステートマシンの制御、キューの管理、内部サブシステムへのアクセスを行うための単一のエントリーポイントです。

```php
use Queuety\Queuety;
```

## コアへのスタンドアロンアクセス

QueuetyのDBバックエンドランタイムは、WordPressの外部で初期化できます。

このスタンドアロン経路は、オーケストレーションコア向けです：

- ジョブとワーカー（ワーカープールには`DB_HOST`、`DB_NAME`、`DB_USER`、`DB_PASSWORD`の定数も必要です。下記を参照）
- ワークフローとシグナル
- ステートマシンとイベント
- アーティファクト、ログ、メトリクス、スケジュール

これはWordPressアダプターの代わりにはなりません。`Queuety::on_action()`、
`replace_wp_cron()`、プラグインのブートストラップ、および実際の`wp queuety ...`
登録経路には、引き続きWordPressが必要です。

### `Queuety::init( Connection $conn )`

DBバックエンドの直接接続でQueuetyを初期化します。

```php
use Queuety\Connection;
use Queuety\Queuety;

$conn = new Connection(
    host: '127.0.0.1:3306',
    dbname: 'wordpress',
    user: 'root',
    password: 'secret',
    prefix: 'wp_',
);

Queuety::init( $conn );
```

オプションの`table_prefix`引数を指定すると、接続ごとにランタイムテーブル名のQueuety部分が変わります：

```php
$conn = new Connection(
    host: '127.0.0.1:3306',
    dbname: 'wordpress',
    user: 'root',
    password: 'secret',
    prefix: 'wp_',
    table_prefix: 'themequeue_',
);
```

これにより、`queuety_jobs`などのテーブルが`wp_themequeue_jobs`として解決されます。

### `Queuety::ensure_schema()`

アクティブな接続にQueuetyランタイムテーブルが存在することを確認します。

```php
Queuety::init( $conn );
Queuety::ensure_schema();
```

モデル全体とWordPressの境界については、[スタンドアロンでの使用](https://queuety.inline0.dev/ja/docs/features/standalone-use)を参照してください。

## ジョブ

### `Queuety::dispatch( $handler, $payload )`

ジョブをディスパッチします。ハンドラー名の文字列または`Contracts\Job`インスタンスを受け取ります。オプションを連結するための`PendingJob`ビルダーを返します。

```php
// Handler name + payload (original API)
Queuety::dispatch( 'send_email', [ 'to' => 'user@example.com' ] );

// Contracts\Job instance (v0.6.0+)
Queuety::dispatch( new SendEmailJob( to: 'user@example.com' ) );

// With options
Queuety::dispatch( 'send_email', [ 'to' => 'user@example.com' ] )
    ->on_queue( 'emails' )
    ->with_priority( Priority::High )
    ->delay( 300 )
    ->max_attempts( 5 )
    ->rate_limit( 10, 60 )
    ->unique()
    ->after( $other_job_id );

// Get the job ID
$job_id = Queuety::dispatch( 'send_email', $payload )->id();
```

`Contracts\Job`インスタンスを渡すと、シリアライザーはFQCNをハンドラー名として、パブリックプロパティをペイロードとして抽出します。`$handler`が`Job`インスタンスの場合、`$payload`パラメーターは無視されます。

### `PendingJob`メソッド

| メソッド | 説明 |
|---|---|
| `on_queue( string $queue )` | 対象のキューを設定 |
| `with_priority( Priority $priority )` | 優先度を設定 |
| `delay( int $seconds )` | ジョブが実行可能になるまでの遅延時間 |
| `max_attempts( int $max )` | 最大再試行回数 |
| `rate_limit( int $max, int $window )` | レート制限：ウィンドウ秒数内の最大実行回数 |
| `unique()` | 重複ディスパッチを防止 |
| `after( int $job_id )` | 別のジョブが先に完了するまで待機 |
| `concurrency_group( string $group, int $limit )` | ジョブを共有ワーカー受付グループに追加 |
| `cost_units( int $units )` | ディスパッチに相対的な実行コストのメタデータを付与 |
| `id()` | 強制的にディスパッチし、ジョブIDを返す |

`concurrency_group()`と`cost_units()`は、より広範な[リソース管理](https://queuety.inline0.dev/ja/docs/features/resource-management)モデルに連携します。そのため、同じディスパッチを件数ベースの同時実行制限、重み付けされたキューまたはプロバイダーの予算、ワーカー受付のヒューリスティックに利用できます。

### `Queuety::dispatch_sync( $handler, $payload )`

キューに追加せず、現在のプロセス内でジョブを同期実行します。

```php
// With a Job instance
Queuety::dispatch_sync( new SendEmailJob( to: 'user@example.com', subject: 'Hi', body: 'Hello' ) );

// With a handler name and payload
Queuety::dispatch_sync( 'send_email', [ 'to' => 'user@example.com' ] );
```

ジョブの`handle()`メソッドを直接呼び出します。データベース行は作成されず、ワーカーも使用されず、ミドルウェアも適用されません。

### `Queuety::batch( $jobs )`

複数のジョブを1つの複数行INSERTでディスパッチします。

```php
$job_ids = Queuety::batch( [
    [ 'handler' => 'send_email', 'payload' => [ 'to' => 'a@example.com' ], 'queue' => 'emails' ],
    [ 'handler' => 'send_email', 'payload' => [ 'to' => 'b@example.com' ], 'priority' => 2 ],
] );
```

### `Queuety::create_batch( $jobs )`

コールバックと進捗追跡機能を使ってジョブのグループをディスパッチする`BatchBuilder`を作成します。詳しくは[バッチ処理](https://queuety.inline0.dev/ja/docs/features/batching)を参照してください。

```php
$batch = Queuety::create_batch( [
    new ImportUsersJob( $chunk_1 ),
    new ImportUsersJob( $chunk_2 ),
] )
    ->name( 'Import users' )
    ->then( ImportCompleteHandler::class )
    ->catch( ImportFailedHandler::class )
    ->finally( ImportCleanupHandler::class )
    ->allow_failures()
    ->on_queue( 'imports' )
    ->dispatch();
```

### `BatchBuilder`メソッド

| メソッド | 戻り値 | 説明 |
|---|---|---|
| `name( string $name )` | `self` | バッチ名を設定 |
| `on_queue( string $queue )` | `self` | バッチ内のすべてのジョブのキューを設定 |
| `then( string $handler_class )` | `self` | バッチが正常に完了したときに呼び出されるハンドラー |
| `catch( string $handler_class )` | `self` | バッチ内の最初のジョブが失敗したときに呼び出されるハンドラー |
| `finally( string $handler_class )` | `self` | バッチの終了時（成功または失敗）に呼び出されるハンドラー |
| `allow_failures()` | `self` | 失敗があっても`then`コールバックを実行できるようにする |
| `dispatch()` | `Batch` | バッチ行とすべてのジョブを作成し、`Batch`値オブジェクトを返す |

### `Queuety::find_batch( $id )`

IDでバッチを検索します。`Batch`値オブジェクトまたは`null`を返します。

```php
$batch = Queuety::find_batch( $batch_id );

if ( null !== $batch ) {
    echo $batch->progress() . '% complete';
}
```

## ワーカー制御

### `Queuety::run_worker( $queue = 'default', $once = false )`

ワーカーループを1回、直接実行します。

```php
Queuety::run_worker( 'default' );
Queuety::run_worker( 'critical,default', true );
```

### `Queuety::run_worker_pool( $workers, $queue = 'default' )`

固定サイズのワーカープールを直接実行します。`pcntl`および`posix`拡張機能が必要です。プールは子接続用にWordPress`DB_HOST`、`DB_NAME`、`DB_USER`、`DB_PASSWORD`定数を読み取ります（テーブルプレフィックスは初期化済み接続から取得されます）。そのため、WordPressの外部でプールを実行する場合は、これらの定数を定義してください（[#5](https://github.com/inline0/queuety/issues/5)）。

```php
Queuety::run_worker_pool( 4, 'providers' );
```

### `Queuety::run_auto_scaling_worker_pool( $min_workers, $max_workers, $queue = 'default' )`

適応型ワーカープールを直接実行します。必要条件は`run_worker_pool()`と同じです。

```php
Queuety::run_auto_scaling_worker_pool( 2, 6, 'providers' );
```

### `Batch`値オブジェクト

| メソッド/プロパティ | 型 | 説明 |
|---|---|---|
| `$id` | `int` | バッチID |
| `$name` | `string\|null` | オプションのバッチ名 |
| `$total_jobs` | `int` | バッチ内のジョブ総数 |
| `$pending_jobs` | `int` | 保留中のジョブ数 |
| `$failed_jobs` | `int` | 失敗したジョブ数 |
| `$failed_job_ids` | `array` | 失敗したジョブのID |
| `$created_at` | `DateTimeImmutable` | バッチの作成日時 |
| `$finished_at` | `DateTimeImmutable\|null` | バッチの終了日時 |
| `$cancelled_at` | `DateTimeImmutable\|null` | バッチのキャンセル日時 |
| `progress()` | `int` | 完了率（0-100） |
| `finished()` | `bool` | バッチが終了したかどうか |
| `has_failures()` | `bool` | 失敗したジョブがあるかどうか |
| `cancelled()` | `bool` | バッチがキャンセルされたかどうか |

### `Queuety::chain( $jobs )`

順次ジョブを実行する`ChainBuilder`を作成します。各ジョブは、直前のジョブが正常に完了することを前提とします。

```php
$first_job_id = Queuety::chain( [
    new FetchDataJob( $url ),
    new ProcessDataJob(),
    new NotifyCompleteJob(),
] )
    ->on_queue( 'pipeline' )
    ->catch( ChainFailedHandler::class )
    ->dispatch();
```

### `ChainBuilder`メソッド

| メソッド | 戻り値 | 説明 |
|---|---|---|
| `on_queue( string $queue )` | `self` | チェーン内のすべてのジョブのキューを設定 |
| `catch( string $handler_class )` | `self` | チェーン内のいずれかのジョブが恒久的に隔離されたときに呼び出されるハンドラー |
| `dispatch()` | `int` | 順次依存関係を設定してすべてのジョブを作成し、最初のジョブIDを返す |

### `Queuety::retry( $job_id )`

特定のジョブを再試行します。ステータスを`pending`にリセットします。

```php
Queuety::retry( 42 );
```

### `Queuety::retry_buried()`

隔離されたすべてのジョブを再試行します。再試行したジョブ数を返します。

```php
$count = Queuety::retry_buried();
```

### `Queuety::purge( $older_than_days )`

完了したジョブを一括削除します。削除したジョブ数を返します。

```php
$count = Queuety::purge();     // uses QUEUETY_RETENTION_DAYS
$count = Queuety::purge( 30 ); // purge jobs older than 30 days
```

## キュー

### `Queuety::stats( $queue )`

ステータス別に集計したジョブ数を取得します。

```php
$stats = Queuety::stats();          // all queues
$stats = Queuety::stats( 'emails' ); // specific queue
// ['pending' => 12, 'processing' => 3, 'completed' => 150, 'failed' => 2, 'buried' => 1]
```

### `Queuety::buried( $queue )`

隔離されたジョブをすべて取得します。

```php
$jobs = Queuety::buried();
$jobs = Queuety::buried( 'emails' );
```

### `Queuety::pause( $queue )`

キューを一時停止し、ワーカーが処理をスキップするようにします。

```php
Queuety::pause( 'emails' );
```

### `Queuety::resume( $queue )`

一時停止中のキューを再開します。

```php
Queuety::resume( 'emails' );
```

### `Queuety::is_paused( $queue )`

キューが一時停止中かどうかを確認します。

```php
if ( Queuety::is_paused( 'emails' ) ) {
    // Queue is paused
}
```

## ワークフロー

### `Queuety::workflow( $name )`

ワークフローの構築を開始します。`WorkflowBuilder`を返します。

```php
$workflow_id = Queuety::workflow( 'generate_report' )
    ->then( FetchDataHandler::class )
    ->then( CallLLMHandler::class )
    ->then( FormatOutputHandler::class )
    ->dispatch( [ 'user_id' => 42 ] );
```

### `WorkflowBuilder`メソッド

| メソッド | 説明 |
|---|---|
| `then( string $handler_class, ?string $name = null )` | 順次ステップを追加します。条件分岐用の名前は任意です。 |
| `parallel( array $handler_classes )` | 並列ステップのグループを追加します。 |
| `for_each( string $items_key, string $handler_class, ?string $result_key = null, ForEachMode $mode = ForEachMode::All, ?int $quorum = null, ?string $reducer_class = null, ?string $name = null )` | ワークフローの状態内の各項目につき1つの分岐ジョブを展開する、動的なfor-eachステップを追加します。 |
| `repeat_while( string $target_step, ?string $state_key = null, mixed $expected = true, ?string $name = null, ?string $condition_class = null, ?int $max_iterations = null )` | パブリック状態キーまたは`RepeatCondition`クラスが一致する間、前の名前付きステップに戻ります。 |
| `repeat_until( string $target_step, ?string $state_key = null, mixed $expected = true, ?string $name = null, ?string $condition_class = null, ?int $max_iterations = null )` | パブリック状態キーまたは`RepeatCondition`クラスが一致するまで、前の名前付きステップに戻ります。 |
| `run_workflow( string $workflow_name, WorkflowBuilder $sub_builder )` | ワークフロー実行ステップを追加します。 |
| `delay( int $seconds = 0, int $minutes = 0, int $hours = 0, int $days = 0 )` | 永続的な遅延ステップを追加します。すべての期間が合算されます。 |
| `wait_for_signal( string $name, ?string $result_key = null, ?string $step_name = null, array $match_payload = [], ?string $correlation_key = null )` | シグナル待機ステップを追加します。無関係なイベントを無視するには、`match_payload`と`correlation_key`を任意で指定できます。 |
| `wait_for_signals( array $signal_names, WaitMode $mode = WaitMode::All, ?string $result_key = null, ?string $name = null, array $match_payload = [], ?string $correlation_key = null )` | ペイロードの照合と相関を任意で指定し、複数のシグナルのすべてまたはいずれかを待機します。 |
| `wait_for_approval( string $signal_name = 'approval', ?string $result_key = 'approval', ?string $name = null, array $match_payload = [], ?string $correlation_key = null )` | 人間による承認シグナルを待機します。 |
| `wait_for_decision( string $approve_signal = 'approved', string $reject_signal = 'rejected', ?string $result_key = 'decision', ?string $name = null, array $match_payload = [], ?string $correlation_key = null )` | 承認または却下を待機し、構造化された判定ペイロードを保存します。 |
| `wait_for_input( string $signal_name = 'input', ?string $result_key = 'input', ?string $name = null, array $match_payload = [], ?string $correlation_key = null )` | 人間による入力シグナルを待機します。 |
| `wait_for_workflow( int\|string $workflow, ?string $result_key = null, ?string $name = null )` | 1つのワークフローID、またはパブリック状態に保存されたワークフローIDの完了を待機します。 |
| `wait_for_workflows( array\|string $workflows, WaitMode $mode = WaitMode::All, ?string $result_key = null, ?string $name = null, ?int $quorum = null )` | 複数のワークフローのすべて、いずれか、または定足数の完了を待機します。 |
| `wait_for_workflow_group( string $group_key, WaitMode $mode = WaitMode::All, ?int $quorum = null, ?string $result_key = null, ?string $name = null )` | 内部グループキーで、以前に開始したワークフローグループの完了を待機します。 |
| `start_workflows( string $items_key, WorkflowBuilder $workflow_builder, string $result_key = 'started_workflow_ids', string $payload_key = 'item', bool $inherit_state = true, ?string $name = null, ?string $group_key = null )` | ランタイム項目ごとにトップレベルのワークフローを1つディスパッチします。開始したワークフロー群に永続的なグループキーを付けることもできます。 |
| `start_agents( string $items_key, WorkflowBuilder $workflow_builder, string $result_key = 'agent_workflow_ids', string $payload_key = 'agent_task', bool $inherit_state = true, ?string $name = null, ?string $group_key = null )` | エージェント向けの`start_workflows()`の別名です。 |
| `wait_for_agents( array\|string $workflows = 'agent_workflow_ids', WaitMode $mode = WaitMode::All, ?string $result_key = 'agent_results', ?string $name = null, ?int $quorum = null )` | エージェント向けの`wait_for_workflows()`の別名です。 |
| `wait_for_agent_group( string $group_key = 'agents', WaitMode $mode = WaitMode::All, ?int $quorum = null, ?string $result_key = 'agent_results', ?string $name = null )` | エージェント向けの`wait_for_workflow_group()`の別名です。 |
| `version( string $version )` | ワークフロー定義にアプリケーションレベルのバージョンを付け、検査やエクスポートに利用できるようにします。 |
| `idempotency_key( string $key )` | 呼び出し元が指定したキーに対して、ワークフローのディスパッチを永続化します。同じキーで再度ディスパッチすると、元のワークフローIDを返します。 |
| `max_transitions( int $max )` | ステップ遷移の完了数が`$max`を超えた場合、ワークフローを失敗させます。 |
| `max_for_each_items( int $max )` | `for_each()`ステップが`$max`を超える項目の展開を試みた場合、ワークフローを失敗させます。 |
| `max_state_bytes( int $bytes )` | パブリック状態が`$bytes`を超えた場合、ワークフローを失敗させます。 |
| `max_cost_units( int $max )` | 完了したステップのコスト単位が`$max`を超えた場合、ワークフローを失敗させます。 |
| `max_started_workflows( int $max )` | 子ワークフローのディスパッチ数が`$max`を超える前に、ワークフローを失敗させます。 |
| `compensate_with( string $handler_class )` | 直前に追加したステップに補償ハンドラーを設定します。 |
| `compensate_on_failure()` | ワークフローの失敗時に、完了済みステップの補償処理を自動実行します。 |
| `on_queue( string $queue )` | すべてのステップのキューを設定します。 |
| `with_priority( Priority $priority )` | すべてのステップの優先度を設定します。 |
| `max_attempts( int $max )` | ステップごとの最大再試行回数を設定します。 |
| `on_cancel( string $handler_class )` | キャンセル時に実行するクリーンアップハンドラークラスを登録します。詳しくは[キャンセル](https://queuety.inline0.dev/ja/docs/workflows/cancellation)を参照してください。 |
| `prune_state_after( int $steps = 2 )` | 状態の自動プルーニングを有効にします。しきい値より古いステップ出力を削除します。詳しくは[状態のプルーニング](https://queuety.inline0.dev/ja/docs/features/state-pruning)を参照してください。 |
| `must_complete_within( int $seconds = 0, int $minutes = 0, int $hours = 0, int $days = 0 )` | ワークフローの期限を設定します。すべての期間が合算されます。詳しくは[期限](https://queuety.inline0.dev/ja/docs/workflows/deadlines)を参照してください。 |
| `on_deadline( string $handler_class )` | ワークフローの期限超過時に呼び出されるハンドラーを登録します。詳しくは[期限](https://queuety.inline0.dev/ja/docs/workflows/deadlines)を参照してください。 |
| `dispatch( array $initial_payload = [] )` | ワークフローをディスパッチし、ワークフローIDを返します。 |

### `Queuety::workflow_status( $workflow_id )`

ワークフローのステータスを取得します。`WorkflowState`オブジェクトまたは`null`を返します。

```php
$state = Queuety::workflow_status( $workflow_id );
echo $state->name;          // 'generate_report'
echo $state->status->value; // 'running'
echo $state->current_step;  // 1
echo $state->total_steps;   // 3
print_r( $state->state );   // accumulated public state array
echo $state->wait_type;     // 'signal' or 'workflow' while blocked
echo $state->wait_mode;     // 'all', 'any', or 'quorum'
echo $state->definition_version; // 'research.v2'
echo $state->definition_hash;    // '4c7a...'
echo $state->idempotency_key;    // 'brief:42:research'
echo $state->artifact_count;     // 2
print_r( $state->budget );       // configured workflow budget + current usage
print_r( $state->wait_details ); // matched/remaining blockers, result key, correlation info
print_r( $state->artifact_keys ); // ['draft', 'citations']
```

`WorkflowState`には、次の情報も含まれます：

- `waiting_for`：現在実行をブロックしているシグナル名またはワークフローID
- `current_step_name`：現在のステップに設定された名前（指定されている場合）
- `wait_mode`：ブロック中の現在の待機モード（`all`、`any`、または`quorum`）
- `wait_details`：照合済みと未処理のブロッカーなど、追加の検査データ
- `definition_version`：`version()`で設定された値（設定されている場合）
- `definition_hash`：ワークフロー定義の決定論的なハッシュ
- `idempotency_key`：永続ディスパッチキー（設定されている場合）
- `budget`：ガードレールが有効な場合の、設定済み制限と現在の使用量
- `artifact_count`：ワークフローに保存されたアーティファクト数
- `artifact_keys`：確認しやすいように表示する、保存済みアーティファクトのキー

### `Queuety::retry_workflow( $workflow_id )`

失敗したステップから、失敗したワークフローを再試行します。

```php
Queuety::retry_workflow( $workflow_id );
```

失敗後にワークフローの補償処理がすでに実行されている場合、`RuntimeException`をスローします。

### `Queuety::pause_workflow( $workflow_id )`

実行中のワークフローを一時停止します。現在のステップですでにキューに追加された作業は完了する場合がありますが、ワークフローを再開するまで後続のステップはキューに追加されません。

```php
Queuety::pause_workflow( $workflow_id );
```

### `Queuety::resume_workflow( $workflow_id )`

一時停止中のワークフローを再開します。

```php
Queuety::resume_workflow( $workflow_id );
```

### `Queuety::cancel_workflow( $workflow_id )`

ワークフローをキャンセルし、登録済みのクリーンアップハンドラーを実行します。ステータスを`cancelled`に設定し、ワークフローの保留中および処理中のジョブをすべて隔離します。

```php
Queuety::cancel_workflow( $workflow_id );
```

ワークフローがすでに`completed`または`cancelled`の場合、`RuntimeException`をスローします。詳しくは[キャンセル](https://queuety.inline0.dev/ja/docs/workflows/cancellation)を参照してください。

### `Queuety::rewind_workflow( $workflow_id, $to_step )`

ワークフローを前のステップに巻き戻し、その位置から再実行します。指定したステップのイベントログ`state_after`から状態が復元され、次のステップがキューに追加されます。

```php
Queuety::rewind_workflow( $workflow_id, to_step: 1 );
```

対象のステップに記録済みの状態がない場合、`RuntimeException`をスローします。[ワークフローイベントログ](https://queuety.inline0.dev/ja/docs/workflows/event-log)が必要です。詳しくは[タイムトラベル](https://queuety.inline0.dev/ja/docs/workflows/time-travel)を参照してください。

### `Queuety::fork_workflow( $workflow_id )`

実行中のワークフローを現在の状態で独立したコピーに分岐します。新しいワークフローIDを返します。

```php
$forked_id = Queuety::fork_workflow( $workflow_id );
```

分岐したワークフローは独自のIDを持ち、元のワークフローとは独立して動作します。詳しくは[分岐](https://queuety.inline0.dev/ja/docs/workflows/forking)を参照してください。

### `Queuety::export_workflow( $workflow_id )`

ワークフローの実行履歴全体を、JSONシリアライズ可能な配列としてエクスポートします。ワークフロー行、すべてのジョブ、ワークフローイベント、ログエントリーが含まれます。

```php
$data = Queuety::export_workflow( $workflow_id );
```

JSONの構造とユースケースについては、[エクスポートとリプレイ](https://queuety.inline0.dev/ja/docs/workflows/export-replay)を参照してください。

### `Queuety::replay_workflow( $data )`

エクスポートしたワークフローを現在の環境でリプレイします。エクスポートデータから新しいワークフローを作成し、新しいワークフローIDを返します。

```php
$new_id = Queuety::replay_workflow( $data );
```

詳しくは[エクスポートとリプレイ](https://queuety.inline0.dev/ja/docs/workflows/export-replay)を参照してください。

### `Queuety::replace_wp_cron()`

組み込みのWordPresscronシステムをQueuetyのスケジューラーに置き換えます。`wp_schedule_event()`、`wp_unschedule_event()`、`wp_get_scheduled_event()`をインターセプトし、定期イベントをQueuetyワーカー経由で処理します。

```php
Queuety::replace_wp_cron();
```

WordPressが読み込まれている場合にのみ動作します。詳しくは[WP-Cronの置き換え](https://queuety.inline0.dev/ja/docs/features/wp-cron)を参照してください。

### `Queuety::restore_wp_cron()`

Queuetycronブリッジフックを削除して、WordPressのデフォルトのcron動作に戻します。

```php
Queuety::restore_wp_cron();
```

制限については[WP-Cronの置き換え](https://queuety.inline0.dev/ja/docs/features/wp-cron)を参照してください。

### `Queuety::signal( $workflow_id, $name, $data )`

ワークフローにシグナルを送信します。ワークフローがこのシグナルを待機中の場合、すぐに再開します。それ以外の場合、シグナルは保存され、ワークフローが対応する`wait_for_signal`ステップに到達したときに処理されます。

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

// With data merged into workflow state
Queuety::signal( $workflow_id, 'approved', [
    'approved_by' => 'admin@example.com',
] );
```

詳しくは[ワークフローシグナル](https://queuety.inline0.dev/ja/docs/workflows/signals)を参照してください。

### `Queuety::approve_workflow( $workflow_id, $data = [], $signal_name = 'approval' )`

承認フロー用の`signal()`のセマンティックラッパーです。

```php
Queuety::approve_workflow( $workflow_id, [
    'reviewer' => 'editor@example.com',
] );
```

### `Queuety::reject_workflow( $workflow_id, $data = [], $signal_name = 'rejected' )`

却下フロー用の`signal()`のセマンティックラッパーです。

```php
Queuety::reject_workflow( $workflow_id, [
    'reason' => 'needs citations',
] );
```

### `Queuety::submit_workflow_input( $workflow_id, $data = [], $signal_name = 'input' )`

構造化された人間の入力用の`signal()`のセマンティックラッパーです。

```php
Queuety::submit_workflow_input( $workflow_id, [
    'notes' => 'Ship after legal review',
] );
```

### `Queuety::put_artifact( $workflow_id, $artifact_key, $content, $kind = 'json', $step_index = null, $metadata = [] )`

ワークフローに永続アーティファクトを1つ保存します。

```php
Queuety::put_artifact(
    $workflow_id,
    'research_brief',
    [ 'summary' => 'done' ],
    'json',
    metadata: [ 'source' => 'agent' ],
);
```

### `Queuety::put_current_artifact( $artifact_key, $content, $kind = 'json', $metadata = [] )`

現在実行中のワークフローステップにアーティファクトを1つ保存します。

```php
Queuety::put_current_artifact(
    'draft',
    [ 'status' => 'ready' ],
    'json',
);
```

### `Queuety::workflow_artifact( $workflow_id, $artifact_key )`

ワークフローに保存されたアーティファクトを1つ取得します。

```php
$artifact = Queuety::workflow_artifact( $workflow_id, 'draft' );
```

### `Queuety::workflow_artifacts( $workflow_id, $include_content = false )`

ワークフローのアーティファクト一覧を取得します。

```php
$artifacts = Queuety::workflow_artifacts( $workflow_id );
```

### `Queuety::delete_workflow_artifact( $workflow_id, $artifact_key )`

ワークフローのアーティファクトを1つ削除します。

```php
Queuety::delete_workflow_artifact( $workflow_id, 'draft' );
```

## ステートマシン

### `Queuety::machine( $name )`

ステートマシンの構築を開始します。`StateMachineBuilder`を返します。

```php
use Queuety\Enums\StateMachineStatus;

$machine_id = Queuety::machine( 'agent_session' )
    ->state( 'awaiting_user' )
    ->on( 'user_message', 'planning' )
    ->state( 'planning' )
    ->action( PlanSessionAction::class )
    ->on( 'planned', 'completed' )
    ->state( 'completed', StateMachineStatus::Completed )
    ->dispatch( [ 'thread_id' => 42 ] );
```

### `StateMachineBuilder`メソッド

| メソッド | 説明 |
|---|---|
| `initial( string $state_name )` | 初期状態を明示的に設定します。 |
| `state( string $state_name, ?StateMachineStatus $terminal_status = null )` | 1つの状態の設定を開始します。 |
| `action( string\|array $action_class )` | 現在の状態に対するキュー登録済みエントリーアクションを登録します。クラス名、または `class`、`payload`、`config` を含む構造化定義を渡します。`payload` は `StateAction::handle()` に `$payload` として渡されます。 |
| `on( string $event, string $target, string\|array\|null $guard_class = null, ?string $name = null )` | 現在の状態からのイベント遷移を1つ登録します。ガードには `action()` と同じ構造化形式を指定できます。 |
| `on_queue( string $queue )` | キュー登録された状態アクションに使用するキューを設定します。 |
| `with_priority( Priority $priority )` | キュー登録された状態アクションの優先度を設定します。 |
| `max_attempts( int $max_attempts )` | キュー登録された状態アクションの再試行上限を設定します。 |
| `version( string $version )` | マシン定義にアプリケーションレベルのバージョンを付与します。 |
| `idempotency_key( string $key )` | 呼び出し元が指定したキーでディスパッチを永続化します。同じキーで再度ディスパッチすると、元のマシンIDが返されます。 |
| `dispatch( array $initial_state = [] )` | マシンをディスパッチして、マシンIDを返します。 |

状態エントリーアクションのクラスでは、ワークフローのステップで使用できるものと同じリソースポリシーキー（`concurrency_group`、`concurrency_limit`、`cost_units`）を受け取るオプションの `config()` メソッドも定義できます。

### `Queuety::dispatch_state_machine_definition( $definition, $initial_state = [], $options = [] )`

シリアライズされたステートマシン定義バンドルをディスパッチします。ほとんどのアプリケーションコードでは `machine()->dispatch()` の使用を推奨します。この低レベルメソッドは、アダプターがビルダーに直接依存せずにマシンを開始できるようにするものです。

```php
$machine_id = Queuety::dispatch_state_machine_definition(
    $definition,
    [ 'thread_id' => 42 ],
    [ 'idempotency_key' => 'thread:42' ],
);
```

### `Queuety::machine_status( $machine_id )`

現在のマシン状態を取得します。`StateMachineState` オブジェクト、または `null` を返します。

```php
$status = Queuety::machine_status( $machine_id );

echo $status->name;               // 'agent_session'
echo $status->status->value;      // 'waiting_event'
echo $status->current_state;      // 'awaiting_review'
print_r( $status->state );        // public machine state
print_r( $status->available_events ); // valid incoming events in the current state
```

`StateMachineState` では、次の情報も取得できます：

- `definition_version`
- `definition_hash`
- `idempotency_key`
- `error_message`
- `current_action`
- `terminal_status`

### `Queuety::machine_event( $machine_id, $event_name, $payload = [] )`

待機中のマシンに外部イベントを1つ送信します。

```php
Queuety::machine_event(
    $machine_id,
    'approve',
    [
        'approved' => true,
        'reviewer' => 'editor@example.com',
    ]
);
```

ペイロードは遷移ガードから利用でき、イベントが受け入れられると公開マシン状態にマージされます。

### `Queuety::list_machines( $limit = 50, $status = null )`

確認用に、永続化されたマシンの行を一覧表示します。

```php
$machines = Queuety::list_machines();
$waiting  = Queuety::list_machines( status: 'waiting_event' );
```

各行には、マシンID、名前、状態、現在の状態、定義バージョン、定義ハッシュ、冪等性キー、ライフサイクルのタイムスタンプが含まれます。

### `Queuety::machine_timeline( $machine_id, $limit = 100, $offset = 0 )`

1台のマシンについて、永続化されたイベントのタイムラインを取得します。

```php
$timeline = Queuety::machine_timeline( $machine_id );
$page_two = Queuety::machine_timeline( $machine_id, 100, 100 );
```

各イベント行には、`id`、`machine_id`、`job_id`、`state_name`、`handler`、`event`、`event_name`、`transition_name`、`queue`、`attempt`、`input`、`output`、`state_before`、`state_after`、`context`、`artifacts`、`chunks`、`error`、`duration_ms`、`created_at` が含まれます。

### `Queuety::machine_trace( $machine_id )`

ステートマシンデバッガー UI 用の正規化されたトレースバンドルを取得します。

```php
$trace = Queuety::machine_trace( $machine_id );
```

トレースには、`machine`、グループ化された `states`、生の `events`、関連付けられたアクション `jobs`、`logs`、`artifacts`、`chunks` が含まれます。

### `Queuety::machine_state_at( $machine_id, $event_id )`

特定のマシントレースイベント後の公開状態を取得します。見つからない場合は `null` を返します。

```php
$state = Queuety::machine_state_at( $machine_id, $event_id );
```

ライフサイクルモデルと使用パターンについては、[ステートマシン](https://queuety.inline0.dev/ja/docs/state-machines) を参照してください。

## ワークフローテンプレート

### `Queuety::define_workflow( $name )`

テンプレートとして使用するワークフロービルダーを作成します。

```php
$builder = Queuety::define_workflow( 'onboarding' )
    ->then( CreateAccountHandler::class )
    ->then( SendWelcomeEmailHandler::class );
```

### `Queuety::register_workflow_template( $builder )`

ワークフローテンプレートを登録します。

```php
Queuety::register_workflow_template( $builder );
```

### `Queuety::run_workflow( $name, $payload, $options = [] )`

登録済みのワークフローテンプレートを名前でディスパッチします。ワークフローIDを返します。

```php
$workflow_id = Queuety::run_workflow( 'onboarding', [ 'email' => 'user@example.com' ] );

$workflow_id = Queuety::run_workflow(
    'onboarding',
    [ 'email' => 'user@example.com' ],
    [ 'idempotency_key' => 'onboarding:user@example.com' ],
);
```

テンプレートが登録されていない場合は `RuntimeException` をスローします。

### `Queuety::dispatch_workflow_definition( $definition, $payload, $options = [] )`

ランタイム定義バンドルからワークフローをディスパッチします。

ほとんどのアプリケーションコードでは `run_workflow()` または `workflow()->dispatch()` の使用を推奨します。この低レベルメソッドは、再利用可能なアダプターが内部のワークフローマネージャーメソッドに依存せず、シリアライズされたワークフロー定義をディスパッチできるようにするものです。

```php
$workflow_id = Queuety::dispatch_workflow_definition(
    $definition,
    [ 'email' => 'user@example.com' ],
    [ 'idempotency_key' => 'onboarding:user@example.com' ],
);
```

### `Queuety::on_action( $hook, $workflow, $map = null, $when = null, $idempotency_key = null, $priority = 10, $accepted_args = null )`

ワークフローをディスパッチする WordPress アクションを登録します。

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

`$workflow` には次のいずれかを指定できます：

- 登録済みのワークフローテンプレート名
- インライン `WorkflowBuilder`

`map`、`when`、`idempotency_key` は、現在の WordPress リクエスト内で同期的に実行されます。ディスパッチ後に非同期で実行されるのは、ワークフローのステップのみです。

詳しいガイドは [アクショントリガー](https://queuety.inline0.dev/ja/docs/features/action-triggers) を参照してください。

### `Queuety::workflow_templates()`

ワークフローテンプレートレジストリを取得します。

```php
$registry = Queuety::workflow_templates();
$template = $registry->get( 'onboarding' ); // WorkflowTemplate or null
```

### `Queuety::load_workflows( $directory, $recursive )`

ディレクトリ内のすべてのワークフローファイルを読み込み、登録します。各 `.php` ファイルは `WorkflowBuilder` を返す必要があります。登録したワークフロー数を返します。

```php
$count = Queuety::load_workflows( __DIR__ . '/workflows/' );
$count = Queuety::load_workflows( __DIR__ . '/workflows/', recursive: true );
```

### `Queuety::load_workflow_file( $file_path )`

単一のワークフローファイルを読み込み、登録します。ファイルがビルダーを返さない場合は、`WorkflowTemplate` または `null` を返します。

```php
$template = Queuety::load_workflow_file( __DIR__ . '/workflows/onboard-user.php' );
```

## スケジュール設定

### `Queuety::schedule( $handler, $payload )`

繰り返しスケジュールを作成します。`PendingSchedule` ビルダーを返します。

```php
Queuety::schedule( 'cleanup_handler' )
    ->every( '1 hour' )
    ->on_queue( 'maintenance' );

Queuety::schedule( 'nightly_report' )
    ->cron( '0 3 * * *' )
    ->on_queue( 'reports' );
```

### `PendingSchedule` メソッド

| メソッド | 説明 |
|---|---|
| `every( string $interval )` | 間隔式を設定します（e.g、`1 hour`、`30 minutes`） |
| `cron( string $expression )` | 5フィールドの cron 式を設定します |
| `overlap( OverlapPolicy $policy )` | 重複実行ポリシーを設定します（既定値：`Allow`）。[スケジュール設定](https://queuety.inline0.dev/ja/docs/features/scheduling) を参照してください。 |
| `on_queue( string $queue )` | 対象キューを設定します（既定値：`default`） |
| `id()` | 強制的にディスパッチし、スケジュールIDを返します |

### `Queuety::scheduler()`

内部 `Scheduler` インスタンスを取得します。

```php
$scheduler = Queuety::scheduler();
$schedules = $scheduler->list();
$scheduler->remove( 'handler_name' );
$count = $scheduler->tick(); // manually trigger
```

## ハンドラーの登録

### `Queuety::register( $name, $class )`

ハンドラークラスを名前で登録します。

```php
Queuety::register( 'send_email', SendEmailHandler::class );
```

### `Queuety::discover_handlers( $directory, $namespace )`

ディレクトリ内のハンドラークラスを自動検出して登録します。登録したハンドラー数を返します。

```php
$count = Queuety::discover_handlers( __DIR__ . '/handlers', 'MyPlugin\\Handlers' );
```

### `Queuety::registry()`

ハンドラーレジストリを取得します。

```php
$registry = Queuety::registry();
```

## オブザーバビリティ

### `Queuety::logger()`

ログエントリーを検索するための `Logger` インスタンスを取得します。

```php
$logger = Queuety::logger();
$logs   = $logger->for_job( 42 );
$logs   = $logger->for_workflow( 7 );
$logs   = $logger->for_handler( 'send_email', 50 );
$logs   = $logger->for_event( LogEvent::Failed, 50 );
$logs   = $logger->since( new \DateTimeImmutable( '-1 hour' ), 100 );
$count  = $logger->purge( 30 );
```

### `Queuety::metrics()`

`Metrics` インスタンスを取得します。

```php
$stats = Queuety::metrics()->handler_stats( 60 ); // last 60 minutes
```

### `Queuety::webhook_notifier()`

`WebhookNotifier` インスタンスを取得します。

```php
$notifier = Queuety::webhook_notifier();
$id       = $notifier->register( 'job.buried', 'https://hooks.slack.com/...' );
$webhooks = $notifier->list();
$notifier->remove( $id );
```

### `Queuety::rate_limiter()`

`RateLimiter` インスタンスを取得します。

```php
$limiter = Queuety::rate_limiter();
$limiter->register( 'call_openai', 60, 60 );
```

## キャッシュ

### `Queuety::cache()`

有効なキャッシュバックエンドのインスタンスを取得します。

```php
$cache = Queuety::cache();
$cache->set( 'my_key', 'my_value', 60 );
$value = $cache->get( 'my_key' );
```

### `Queuety::set_cache( $cache )`

キャッシュバックエンドを上書きします。カスタム実装を使用するには、`Queuety::init()` の前に呼び出してください。

```php
Queuety::set_cache( new RedisCache() );
Queuety::init( $connection );
```

### `QUEUETY_CACHE_TTL`

既定のキャッシュTTL（秒）（既定値：`5`）。内部キャッシュ操作で使用する既定のTTLを変更するには、`wp-config.php` でこの定数を設定します。

```php
define( 'QUEUETY_CACHE_TTL', 10 );
```

バックエンドと自動検出の詳細は、[キャッシュ](https://queuety.inline0.dev/ja/docs/features/caching) を参照してください。

## ステートマシンのイベントログ

### `Queuety::machine_events()`

`StateMachineEventLog` インスタンスを取得します。

```php
$log = Queuety::machine_events();
```

## ワークフローイベントログ

### `Queuety::workflow_events()`

`WorkflowEventLog` インスタンスを取得します。

```php
$log = Queuety::workflow_events();
```

### `Queuety::workflow_timeline( $workflow_id, $limit = 100, $offset = 0 )`

ワークフローのイベント全体のタイムラインを取得します。イベント行をID順に並べた配列を返します。

```php
$events = Queuety::workflow_timeline( $workflow_id );
$next   = Queuety::workflow_timeline( $workflow_id, 100, 100 );
```

各イベント行には、`id`、`workflow_id`、`job_id`、`parent_event_id`、`step_index`、`step_name`、`step_type`、`handler`、`event`、`queue`、`attempt`、`input`、`output`、`state_before`、`state_after`、`context`、`artifacts`、`chunks`、`error`、`error_message`（`error.message` からコピー）、`duration_ms`、`created_at` が含まれます。

### `Queuety::workflow_trace( $workflow_id )`

ワークフローデバッガー UI 用の正規化されたトレースバンドルを取得します。

```php
$trace = Queuety::workflow_trace( $workflow_id );
```

トレースには、`workflow`、グループ化された `steps`、生の `events`、`jobs`、`logs`、`artifacts`、`chunks`、`signals`、`wait_dependencies` が含まれます。

### `Queuety::trace_input( $input )`

現在実行中のワークフローステップに、アプリケーションレベルの入力を設定します。

### `Queuety::trace_output( $output )`

現在実行中のワークフローステップに、アプリケーションレベルの出力を設定します。

### `Queuety::trace_context( array $context )`

現在実行中のワークフローステップに、アプリケーションレベルのコンテキストをマージします。

### `Queuety::workflow_state_at( $workflow_id, $step_index )`

特定のワークフローステップの完了後または再開後の公開状態を取得します。見つからない場合は `null` を返します。

```php
$state = Queuety::workflow_state_at( $workflow_id, 2 );
```

ユースケースと CLI コマンドについては、[ワークフローイベントログ](https://queuety.inline0.dev/ja/docs/workflows/event-log) を参照してください。

## 内部インスタンス

これらのメソッドは、高度なユースケース向けの内部インスタンスを返します。

| メソッド | 戻り値 | 説明 |
|---|---|---|
| `Queuety::queue()` | `Queue` | キュー操作（claim、release、bury） |
| `Queuety::worker()` | `Worker` | ワーカープロセス制御 |
| `Queuety::workflow_manager()` | `Workflow` | ワークフローのオーケストレーション |
| `Queuety::machines()` | `StateMachine` | ステートマシンのライフサイクル管理 |
| `Queuety::connection()` | `Connection` | データベース接続 |
| `Queuety::batch_manager()` | `BatchManager` | バッチのライフサイクル管理（キャンセル、整理） |
| `Queuety::chunk_store()` | `ChunkStore` | ストリーミングステップ用チャンクの永続化 |
| `Queuety::machine_events()` | `StateMachineEventLog` | ステートマシンのトレースイベントと正規化されたトレースバンドル |
| `Queuety::workflow_events()` | `WorkflowEventLog` | ワークフローのトレースイベントと正規化されたトレースバンドル |
| `Queuety::resource_manager()` | `ResourceManager` | ワーカーのアドミッションプロファイル、重み付き予算、システムメモリの検査 |
| `Queuety::cache()` | `Cache` | キャッシュバックエンドのインスタンス |

## テスト

### `Queuety::fake()`

テスト用にキューをインメモリのフェイクに置き換えます。データベースに触れずにディスパッチされたジョブを記録する `QueueFake` インスタンスを返します。`create_batch()` はフェイクのバッチメタデータも記録します。チェーンは、ディスパッチされた個々のプッシュ済みジョブを使って検証します。

```php
$fake = Queuety::fake();
SendEmailJob::dispatch( 'user@example.com', 'Hello', 'Hi!' );
$fake->assert_pushed( SendEmailJob::class );
```

### `Queuety::reset()`

キューのフェイクを含むすべての内部状態をリセットします。テストでは `tearDown()` 内で呼び出してください。

```php
Queuety::reset();
```

### `QueueFake` メソッド

| メソッド | 説明 |
|---|---|
| `assert_pushed( string $class, ?Closure $callback )` | ジョブクラスがプッシュされたことをアサートします。オプションのコールバックでジョブデータを絞り込めます。 |
| `assert_pushed_times( string $class, int $count )` | ジョブが正確にN回プッシュされたことをアサートします。 |
| `assert_not_pushed( string $class )` | ジョブが一度もプッシュされていないことをアサートします。 |
| `assert_nothing_pushed()` | ジョブが一切プッシュされていないことをアサートします。 |
| `assert_batched( ?Closure $callback )` | バッチがディスパッチされたことをアサートします。オプションのコールバックでバッチデータを絞り込めます。 |
| `pushed( string $class )` | クラスの記録済みディスパッチをすべて取得します。配列を返します。 |
| `batches()` | 記録済みのバッチをすべて取得します。配列を返します。 |
| `reset()` | 記録済みのジョブとバッチをすべて消去します。 |

詳しい例は [テスト](https://queuety.inline0.dev/ja/docs/features/testing) を参照してください。

## インターフェース

### `Handler`

シンプルなジョブハンドラー用のインターフェースです。

```php
interface Handler {
    public function handle( array $payload ): void;
    public function config(): array;
}
```

`config()` は `queue`、`max_attempts`、`backoff`、`rate_limit`、`concurrency_group`、`concurrency_limit`、`cost_units` を返す場合があります。

### `Step`

ワークフローステップのハンドラー用インターフェースです。

```php
interface Step {
    public function handle( array $state ): array;
    public function config(): array;
}
```

`config()` は `max_attempts`、`backoff`、`concurrency_group`、`concurrency_limit`、`cost_units` を返す場合があります。

### `Contracts\ForEachHandler`

動的なfor-each分岐ハンドラー用のインターフェースです。

```php
namespace Queuety\Contracts;

interface ForEachHandler {
    public function handle_item( array $state, mixed $item, int $index ): array;
    public function config(): array;
}
```

`config()` は `max_attempts`、`backoff`、`rate_limit`、`concurrency_group`、`concurrency_limit`、`cost_units` を返す場合があります。

### `Contracts\ForEachReducer`

for-eachの結果用のオプションのリデューサーです。

```php
namespace Queuety\Contracts;

interface ForEachReducer {
    public function reduce( array $state, array $for_each ): array;
}
```

### `Contracts\Compensation`

ステップ補償ハンドラー用のインターフェースです。

```php
namespace Queuety\Contracts;

interface Compensation {
    public function handle( array $state ): void;
}
```

### `Contracts\RepeatCondition`

状態キーの比較では不十分な場合に `repeat_until()` および `repeat_while()` が使用するループ述語用インターフェースです。

```php
namespace Queuety\Contracts;

interface RepeatCondition {
    public function matches( array $state ): bool;
}
```

### `Contracts\StateAction`

キュー登録された状態エントリーアクション用のインターフェースです。

```php
namespace Queuety\Contracts;

interface StateAction {
    public function handle( array $state, ?string $event = null, array $event_payload = [], array $payload = [] ): array|string;
}
```

`$payload` は、マシン定義に構造化された `payload` が含まれている場合、それを受け取ります。公開状態の更新を返します。アクションによって即時に遷移させる場合は、`_event` と、必要に応じて `_event_payload` を含めます。

状態アクションでは、オプションの `config()` メソッドも定義できます。エントリーアクションがキューに登録されると、Queuety はそこから `concurrency_group`、`concurrency_limit`、`cost_units` を読み取ります。

### `Contracts\StateGuard`

ステートマシンの遷移ガード用インターフェースです。

```php
namespace Queuety\Contracts;

interface StateGuard {
    public function allows( array $state, array $event_payload, string $event, array $payload = [] ): bool;
}
```

### `Contracts\Job`

自己完結型でディスパッチ可能なジョブクラス用のインターフェースです。ジョブクラスはペイロードを公開プロパティとして、実行ロジックを `handle()` にカプセル化します。

```php
namespace Queuety\Contracts;

interface Job {
    public function handle(): void;
}
```

ジョブクラスでは、`Contracts\Middleware` インスタンスの配列を返す `middleware()` メソッドを任意で定義できます。

### `Contracts\Cache`

キャッシュバックエンド用のインターフェースです。組み込みの実装とカスタムバックエンドについては、[キャッシュ](https://queuety.inline0.dev/ja/docs/features/caching) を参照してください。

```php
namespace Queuety\Contracts;

interface Cache {
    public function get( string $key ): mixed;
    public function set( string $key, mixed $value, int $ttl = 0 ): void;
    public function delete( string $key ): void;
    public function has( string $key ): bool;
    public function add( string $key, mixed $value, int $ttl = 0 ): bool;
    public function flush(): void;
}
```

| メソッド | 戻り値 | 説明 |
|---|---|---|
| `get( $key )` | `mixed` | 値を取得します。見つからない場合、または期限切れの場合は `null` を返します。 |
| `set( $key, $value, $ttl )` | `void` | 値を保存します。TTLが0の場合、期限切れになりません。 |
| `delete( $key )` | `void` | 値を削除します。 |
| `has( $key )` | `bool` | キーが存在し、期限切れでないことを確認します。 |
| `add( $key, $value, $ttl )` | `bool` | アトミックな「未存在時のみ設定」です。値が設定された場合は `true` を返します。 |
| `flush()` | `void` | キャッシュからすべての項目を削除します。 |

### `WorkflowEventLog`

ワークフローステップの遷移を、完全なトレースコンテキストとともに記録します。`Queuety::workflow_events()` からアクセスできます。

| メソッド | 戻り値 | 説明 |
|---|---|---|
| `record_event( array $event )` | `void` | 生のトレースイベントを記録します |
| `record_step_started( ... )` | `void` | 入力と実行前の状態を含むstep_startedイベントを記録します |
| `record_step_completed( ... )` | `void` | 入力、出力、実行前の状態、実行後の状態を含むstep_completedイベントを記録します |
| `record_step_failed( ... )` | `void` | トレースコンテキストと構造化されたエラー詳細を含むstep_failedイベントを記録します |
| `get_timeline( int $workflow_id, ?int $limit = 100, int $offset = 0 )` | `array` | ワークフローのトレースイベントを順番に取得します。ページングは任意です |
| `get_trace( int $workflow_id )` | `array` | 正規化されたトレースバンドルを取得します |
| `get_state_at_step( int $workflow_id, int $step_index )` | `array\|null` | 特定のステップ完了後または再開後の公開状態を取得します |
| `prune( int $older_than_days )` | `int` | 指定日数より古いイベントを削除します。削除した行数を返します |

### `StateMachineEventLog`

ワークフローイベントと同じトレースフィールドを使って、ステートマシンのライフサイクル、アクション、遷移、ガードのイベントを記録します。

| メソッド | 戻り値 | 説明 |
|---|---|---|
| `record_event( array $event )` | `void` | 生のマシントレースイベントを記録します |
| `get_timeline( int $machine_id, ?int $limit = 100, int $offset = 0 )` | `array` | マシンのトレースイベントを順番に取得します。ページングは任意です |
| `get_trace( int $machine_id )` | `array` | 正規化されたマシントレースバンドルを取得します |
| `get_state_at_event( int $machine_id, int $event_id )` | `array\|null` | 特定のマシントレースイベント後の公開状態を取得します |
| `prune( int $older_than_days )` | `int` | 指定日数より古いイベントを削除します。削除した行数を返します |

### `Contracts\StreamingStep`

チャンクのストリームを生成するワークフローステップハンドラー用のインターフェースです。生成された値はそれぞれ直ちにデータベースに保存されます。[ストリーミングステップ](https://queuety.inline0.dev/ja/docs/workflows/streaming) を参照してください。

```php
namespace Queuety\Contracts;

interface StreamingStep {
    public function stream( array $state, array $existing_chunks = [] ): \Generator;
    public function on_complete( array $chunks, array $state ): array;
    public function config(): array;
}
```

| メソッド | 説明 |
|---|---|
| `stream( $state, $existing_chunks )` | 文字列チャンクを生成するジェネレーターです。生成のたびにデータベースへ即時書き込みが行われます。再試行時には、以前に永続化されたチャンクが `$existing_chunks` に含まれます。 |
| `on_complete( $chunks, $state )` | ストリームの終了後に呼び出されます。ワークフロー状態にマージするデータを返します。 |
| `config()` | オプションの設定です。`max_attempts`、`backoff`、`concurrency_group`、`concurrency_limit`、`cost_units` をサポートします。 |

### `ChunkStore`

ストリーミングステップ用のチャンク永続化を管理します。`Queuety::chunk_store()` からアクセスできます。

| メソッド | 戻り値 | 説明 |
|---|---|---|
| `get_chunks( int $job_id )` | `string[]` | ジョブの全チャンクをチャンクインデックス順に取得します |
| `append_chunk( int $job_id, int $chunk_index, string $content, ?int $workflow_id, ?int $step_index )` | `void` | 1つのチャンクを追加します |
| `clear_chunks( int $job_id )` | `void` | ジョブの全チャンクを削除します |
| `chunk_count( int $job_id )` | `int` | ジョブのチャンク数を数えます |
| `get_accumulated( int $job_id )` | `string` | 全チャンクを1つの文字列に連結します |

### `Heartbeat`

ステップハンドラーやストリーミングステップ内からアクティビティのハートビートを送信するための静的ヘルパーです。[ハートビート](https://queuety.inline0.dev/ja/docs/features/heartbeats) を参照してください。

| メソッド | 説明 |
|---|---|
| `Heartbeat::init( int $job_id, Connection $conn )` | ジョブコンテキストを設定します。ワーカーが自動的に呼び出します。 |
| `Heartbeat::beat( array $progress = [] )` | ハートビートを送信します。`reserved_at` を更新し、必要に応じて進捗データを `heartbeat_data` に保存します。 |
| `Heartbeat::clear()` | ジョブコンテキストをクリアします。ワーカーが自動的に呼び出します。 |
| `Heartbeat::current_job_id()` | 現在のジョブIDを取得します（テスト用）。 |

### `Contracts\Middleware`

ジョブミドルウェア用のインターフェースです。ミドルウェアは、ジョブの実行を玉ねぎ型のパイプラインで包みます。

```php
namespace Queuety\Contracts;

interface Middleware {
    public function handle( object $job, \Closure $next ): void;
}
```

## トレイト

### `Dispatchable`

`Contracts\Job` を実装するジョブクラスに静的なディスパッチメソッドを提供します。コンストラクターの引数は、ジョブインスタンスの作成時に渡されます。

```php
use Queuety\Contracts\Job;
use Queuety\Dispatchable;

class SendEmailJob implements Job {
    use Dispatchable;
    // ...
}

// Dispatches a new SendEmailJob instance
SendEmailJob::dispatch( 'user@example.com', 'Subject', 'Body' );
```

| メソッド | 戻り値 | 説明 |
|---|---|---|
| `dispatch( ...$args )` | `PendingJob` | インスタンスを作成してディスパッチします |
| `dispatch_if( bool $condition, ...$args )` | `PendingJob\|null` | `$condition` がtrueの場合のみディスパッチします |
| `dispatch_unless( bool $condition, ...$args )` | `PendingJob\|null` | `$condition` がfalseの場合のみディスパッチします |
| `with_chain( array $jobs )` | `ChainBuilder` | このジョブクラスからチェーンを開始します |

```php
// Conditional dispatch
SendEmailJob::dispatch_if( $user->wants_email, $user->email, 'Hello', 'Hi!' );
SendEmailJob::dispatch_unless( $maintenance_mode, $user->email, 'Hello', 'Hi!' );

// Chain from a job class
FetchDataJob::with_chain( [
    new ProcessDataJob(),
    new NotifyCompleteJob(),
] )->dispatch();
```

### ジョブのプロパティ

ジョブクラスでは、ワーカーがリフレクションを使って読み取り、再試行やタイムアウトの動作を上書きできる公開プロパティを宣言できます。

| プロパティ | 型 | 説明 |
|---|---|---|
| `$tries` | `int` | ジョブが隔離されるまでの最大試行回数 |
| `$timeout` | `int` | 最大実行時間（秒）（`pcntl` が必要） |
| `$backoff` | `array` | 各再試行の遅延時間（秒）。試行ごとに段階的に増加します |

```php
class ImportProductsJob implements Job {
    use Dispatchable;

    public int $tries = 5;
    public int $timeout = 120;
    public array $backoff = [ 10, 30, 60, 120 ];

    // ...
}
```

### `failed()` フック

ジョブがすべての再試行を使い切って隔離されると、定義されている場合、ワーカーはジョブインスタンスの `failed()` メソッドを呼び出します。

```php
public function failed( \Throwable $exception ): void {
    error_log( "Job failed: {$exception->getMessage()}" );
}
```

## 組み込みミドルウェア

すべてのミドルウェアクラスは `Contracts\Middleware` を実装し、`Queuety\Middleware` 名前空間に配置されています。

| クラス | 説明 |
|---|---|
| `RateLimited( int $max, int $window )` | `$window`秒ごとの実行回数を`$max`回に制限します |
| `Timeout( int $seconds )` | `pcntl`が必要です。`$seconds`秒後にジョブを終了します |
| `UniqueJob( ?string $key )` | データベースロックで同時実行を防ぎます |
| `WithoutOverlapping( string $key, int $release_after )` | ロックの自動期限切れにより重複実行を防ぎます |
| `ThrottlesExceptions( int $max_attempts, int $decay_minutes )` | 外部サービスの停止時にジョブが大量発生しないよう、例外を抑制します |

使い方と例については[Middleware](https://queuety.inline0.dev/ja/docs/features/middleware)を参照してください。

## 列挙型

### `Priority`

```php
enum Priority: int {
    case Low    = 0;
    case Normal = 1;
    case High   = 2;
    case Urgent = 3;
}
```

### `JobStatus`

```php
enum JobStatus: string {
    case Pending    = 'pending';
    case Processing = 'processing';
    case Completed  = 'completed';
    case Failed     = 'failed';
    case Buried     = 'buried';
}
```

### `WorkflowStatus`

```php
enum WorkflowStatus: string {
    case Running        = 'running';
    case Completed      = 'completed';
    case Failed         = 'failed';
    case Paused         = 'paused';
    case WaitingForSignal  = 'waiting_for_signal';
    case WaitingForWorkflows = 'waiting_for_workflows';
    case Cancelled      = 'cancelled';
}
```

### `StateMachineStatus`

```php
enum StateMachineStatus: string {
    case Running = 'running';
    case WaitingEvent = 'waiting_event';
    case Completed = 'completed';
    case Failed = 'failed';
    case Paused = 'paused';
    case Cancelled = 'cancelled';
}
```

### `BackoffStrategy`

```php
enum BackoffStrategy: string {
    case Fixed       = 'fixed';
    case Linear      = 'linear';
    case Exponential = 'exponential';
}
```

### `ForEachMode`

```php
enum ForEachMode: string {
    case All = 'all';
    case FirstSuccess = 'first_success';
    case Quorum = 'quorum';
}
```

### `WaitMode`

```php
enum WaitMode: string {
    case All    = 'all';
    case Any    = 'any';
    case Quorum = 'quorum';
}
```

### `LogEvent`

```php
enum LogEvent: string {
    case Started                  = 'started';
    case Completed                = 'completed';
    case Failed                   = 'failed';
    case Buried                   = 'buried';
    case Retried                  = 'retried';
    case WorkflowStarted          = 'workflow_started';
    case WorkflowCompleted        = 'workflow_completed';
    case WorkflowFailed           = 'workflow_failed';
    case WorkflowPaused           = 'workflow_paused';
    case WorkflowResumed          = 'workflow_resumed';
    case WorkflowCancelled        = 'workflow_cancelled';
    case WorkflowRewound          = 'workflow_rewound';
    case WorkflowForked           = 'workflow_forked';
    case WorkflowDeadlineExceeded = 'workflow_deadline_exceeded';
    case Debug                    = 'debug';
}
```

### `OverlapPolicy`

```php
enum OverlapPolicy: string {
    case Allow  = 'allow';
    case Skip   = 'skip';
    case Buffer = 'buffer';
}
```

各ポリシーの動作については[Scheduling](https://queuety.inline0.dev/ja/docs/features/scheduling)を参照してください。

## 属性

### `#[QueuetyHandler]`

自動登録用のPHP 8属性です。[PHP Attributes](https://queuety.inline0.dev/ja/docs/features/attributes)を参照してください。

```php
use Queuety\Attributes\QueuetyHandler;

#[QueuetyHandler( name: 'send_email', queue: 'emails', max_attempts: 5 )]
class SendEmailHandler implements Handler {
    // ...
}
```

## CLIブリッジ

### `Queuety::cli_command()`

公開されているWP-CLIのルートコマンド名を返します。

既定のルートコマンドは`queuety`です。別の名前でコマンドを公開する場合は、Queuetyの起動前に`QUEUETY_CLI_COMMAND`を定義してください。

### `Queuety::cli_command_map()`

WP-CLIのクラスをスクレイピングせずに、公開済みコマンドの構成を把握する必要があるテストハーネス向けに、シリアライズ可能なQueuety CLIカタログを返します。

各エントリには次の情報が含まれます。
- 安定した操作ID
- 相対CLIパス
- WP-CLIのハンドラークラスとメソッド
- 実行先の候補
- 生のCLI引数を実行プランに正規化するアダプター

### `Queuety::resolve_cli_command( $path, $args, $assoc_args )`

解析済みのCLI呼び出しを、テストハーネスが実行する実行プランに変換します。

```php
$plan = Queuety::resolve_cli_command(
    [ 'workflow', 'export' ],
    [ '42' ],
    [ 'output' => '/tmp/workflow.json' ]
);

echo $plan['callable']; // Queuety\Queuety::export_workflow_to_file
print_r( $plan['arguments'] );
```

実行プランは意図的にトランスポートを考慮しています。
- コマンドは、正規化された引数を使って公開PHP呼び出し可能オブジェクトに解決されます
- カタログには実行先の候補がすべて事前に記載され、`callable`と`transport`によって解析済み入力に応じて選ばれた分岐が示されます

これは、エージェント用テストハーネスでQueuetyが使う標準形です。安定した操作ID、公開APIの実行先、そしてキューの既定値、JSONペイロードのデコード、ワーカープールの分岐、ワークフローのエクスポートファイル処理といったCLI固有の処理を担うアダプターを備えます。
