
# はじめに

## インストール

### 要件

- PHP 8.2以降、WordPress 6.4以降
- MySQL 8.0+ または MariaDB 10.6+。ワーカーは `SELECT ... FOR UPDATE SKIP LOCKED` を使ってジョブと期限到来済みのスケジュールを取得します。古いサーバーでは構文エラーになります。
- `mysqli` または `pdo_mysql`（下記を参照）
- `wp queuety work` を使って専用ワーカーを実行する場合、サーバーに WP-CLI が必要
- `--workers` または `--min-workers`/`--max-workers` を使ってワーカープールを実行する場合、`pcntl` と `posix` の PHP 拡張機能が必要

Queuety は、WordPress と WP-CLI を読み込む PHP ランタイムに `mysqli` または `pdo_mysql` のいずれかを必要とします。ドライバーは自動的に選択され、WordPress ランタイムでは `mysqli` が優先され、スタンドアロンまたは直接のランタイム使用では `pdo_mysql` も利用できます。

WordPress プラグイン層を使わずにDBバックエンドのランタイムを使用する場合は、[スタンドアロンでの使用](https://queuety.inline0.dev/ja/docs/features/standalone-use)を参照してください。この方法では同じ接続とランタイムテーブルを使用しますが、WordPress フックブリッジと WP-CLI 登録は含まれません。

### リリースzipから

各[GitHub リリース](https://github.com/inline0/queuety/releases)には `queuety.zip` アセットがあります。Composerの依存関係をインストール済みのプラグインです。WP-CLI で最新のものをインストールします。

```bash
wp plugin install https://github.com/inline0/queuety/releases/latest/download/queuety.zip --activate
```

zipをダウンロードして、プラグイン > 新規追加 > プラグインのアップロードからアップロードすることもできます。一般的な WordPress サイトには、これが最も簡単な方法です。

### Composer管理の WordPress にComposer経由でインストールする

```bash
composer require queuety/queuety
```

次にプラグインを有効化します:

```bash
wp plugin activate queuety
```

パッケージタイプは `wordpress-plugin` です。Composerがプラグインディレクトリに配置するのは、プロジェクトが `composer/installers` を要求し、そのタイプをBedrockのようにインストール先のパスへマッピングしている場合のみです。また、プロジェクト独自の `vendor/autoload.php` を読み込む必要があります（Bedrockではこの処理も行われます）。`composer/installers` がない場合、Composerは `vendor/queuety/queuety` にインストールしますが、WordPress はそこを認識できません。そのため、通常の WordPress インストールではリリースzipを使ってください。

### 開発中にソースからインストールする

リポジトリを `wp-content/plugins/queuety` に配置し、PHP の依存関係をインストールします:

```bash
composer install
wp plugin activate queuety
```

有効化すると、Queuety はデータベーステーブル（`queuety_jobs`、`queuety_workflows`、`queuety_logs`、`queuety_schedules`、`queuety_queue_states`、`queuety_webhooks`、`queuety_locks`、`queuety_signals`、`queuety_workflow_dependencies`、`queuety_workflow_dispatch_keys`、`queuety_batches`、`queuety_chunks`、`queuety_workflow_events`、`queuety_artifacts`、`queuety_state_machines`、`queuety_state_machine_events`）を作成し、ワーカーがMySQLから直接ジョブを取得できるようにします。

既定では、プラグインは `default` キュー用に WordPress cron を使い、毎分ワンショットのワーカーもスケジュールします。WordPress cron が実行されていれば、`default` 上で動作するジョブとワークフローを、シェルを使わずに実行できます。各実行で処理されるジョブは最大1つで、繰り返しスケジュールの実行、古いジョブの復旧、ワークフローの期限チェックは行いません。これらは長時間稼働する `wp queuety work` プロセス内でのみ実行されます（[#14](https://github.com/inline0/queuety/issues/14)）。独自のキュー、繰り返しスケジュール、低レイテンシ、または高負荷のワークロードには、専用の `wp queuety work` プロセスに移行してください。

## 設定

すべての定数は任意です。プラグインの読み込み前、またはテーマに埋め込む形式でインストールした場合は Queuety の起動前に、`wp-config.php` で定義します:

| 定数 | デフォルト | 説明 |
|---|---|---|
| `QUEUETY_RETENTION_DAYS` | `7` | `wp queuety purge`および`Queuety::purge()`のデフォルトの保持日数。自動削除は行われません |
| `QUEUETY_LOG_RETENTION_DAYS` | `0` | `Config::log_retention_days()`で読み取られますが、まだ使用されていません。`Queuety::purge_logs()`を呼び出すまでログは保持されます（[#15](https://github.com/inline0/queuety/issues/15)） |
| `QUEUETY_MAX_EXECUTION_TIME` | `300` | タイムアウトまでのジョブごとの最大秒数（まだ適用されません。[ジョブ](https://queuety.inline0.dev/ja/docs/jobs#timeout)を参照） |
| `QUEUETY_WORKER_SLEEP` | `1` | キューが空のときにスリープする秒数 |
| `QUEUETY_WORKER_MAX_JOBS` | `1000` | ワーカーが再起動するまでの最大ジョブ数 |
| `QUEUETY_WORKER_MAX_MEMORY` | `128` | ワーカーが再起動するまでの最大MB数 |
| `QUEUETY_RETRY_BACKOFF` | `exponential` | バックオフ戦略: `exponential`、`linear`、または`fixed` |
| `QUEUETY_STALE_TIMEOUT` | `600` | 停滞したジョブが復旧されるまでの秒数 |
| `QUEUETY_CACHE_TTL` | `5` | デフォルトのキャッシュTTL（秒） |
| `QUEUETY_DEBUG` | `false` | ワーカーの詳細ログを有効にする |
| `QUEUETY_CLI_COMMAND` | `queuety` | WP-CLIのルートコマンド名 |
| `QUEUETY_TABLE_PREFIX` | `queuety_` | WordPressデータベースプレフィックスの後に続く、すべてのQueuetyテーブル共通のベース名 |
| `QUEUETY_TABLE_JOBS` | `queuety_jobs` | ジョブテーブル名 |
| `QUEUETY_TABLE_WORKFLOWS` | `queuety_workflows` | ワークフローテーブル名 |
| `QUEUETY_TABLE_LOGS` | `queuety_logs` | ログテーブル名 |
| `QUEUETY_TABLE_SCHEDULES` | `queuety_schedules` | スケジュールテーブル名 |
| `QUEUETY_TABLE_SIGNALS` | `queuety_signals` | シグナルテーブル名 |
| `QUEUETY_TABLE_WORKFLOW_DEPENDENCIES` | `queuety_workflow_dependencies` | ワークフロー依存関係待機テーブル名 |
| `QUEUETY_TABLE_WORKFLOW_DISPATCH_KEYS` | `queuety_workflow_dispatch_keys` | 永続ワークフローの冪等性テーブル名 |
| `QUEUETY_TABLE_CHUNKS` | `queuety_chunks` | ストリーミングチャンクテーブル名 |
| `QUEUETY_TABLE_QUEUE_STATES` | `queuety_queue_states` | キュー状態テーブル名 |
| `QUEUETY_TABLE_WEBHOOKS` | `queuety_webhooks` | Webhookテーブル名 |
| `QUEUETY_TABLE_LOCKS` | `queuety_locks` | ロックテーブル名 |
| `QUEUETY_TABLE_BATCHES` | `queuety_batches` | バッチテーブル名 |
| `QUEUETY_TABLE_WORKFLOW_EVENTS` | `queuety_workflow_events` | ワークフローイベントログテーブル名 |
| `QUEUETY_TABLE_ARTIFACTS` | `queuety_artifacts` | ワークフロー成果物テーブル名 |
| `QUEUETY_TABLE_STATE_MACHINES` | `queuety_state_machines` | ステートマシンテーブル名 |
| `QUEUETY_TABLE_STATE_MACHINE_EVENTS` | `queuety_state_machine_events` | ステートマシンイベントログテーブル名 |
| `QUEUETY_DB_DRIVER` | `auto` | MySQLドライバー: `auto`、`mysqli`、または`pdo`。`auto`はWordPressが読み込まれている場合は`mysqli`を優先し、そうでなければ`pdo_mysql`、次に`mysqli`を使います |

リソースの受け入れ制御と適応型プールの定数（`QUEUETY_RESOURCE_*`、`QUEUETY_WORKER_POOL_*`）は、[ワーカー](https://queuety.inline0.dev/ja/docs/features/workers)]ページに記載されています。

`QUEUETY_TABLE_PREFIX`が変更するのはテーブル名のQueuety部分のみです。WordPressデータベースプレフィックスは引き続き結果全体に付くため、`$wpdb->prefix = 'wp_'`と`QUEUETY_TABLE_PREFIX = 'themequeue_'`を指定すると、`wp_themequeue_jobs`のようなテーブル名になります。個別のテーブルについては、明示的に指定した`QUEUETY_TABLE_*`定数が優先されます。

スタンドアロン接続では、接続ごとにQueuetyテーブルプレフィックスを設定することもできます:

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

これにより、WordPressデータベースプレフィックスをそのまま保ち、Queuetyテーブル部分のみを変更します。

## 最初のジョブ

`Handler`インターフェースを実装するハンドラークラスを作成します:

```php
use Queuety\Handler;

class SendEmailHandler implements Handler {
    public function handle( array $payload ): void {
        wp_mail( $payload['to'], $payload['subject'], $payload['body'] );
    }

    public function config(): array {
        return [
            'queue'           => 'emails',
            'max_attempts'    => 5,
        ];
    }
}
```

登録してディスパッチします:

```php
use Queuety\Queuety;

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

Queuety::dispatch( 'send_email', [
    'to'      => 'user@example.com',
    'subject' => 'Welcome',
    'body'    => 'Hello from Queuety!',
] );
```

または、モダンなディスパッチ可能ジョブクラスを使います:

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

readonly class SendEmailJob implements Job {
    use Dispatchable;

    public function __construct(
        public string $to,
        public string $subject,
        public string $body,
    ) {}

    public function handle(): void {
        wp_mail( $this->to, $this->subject, $this->body );
    }
}

SendEmailJob::dispatch( 'user@example.com', 'Welcome', 'Hello from Queuety!' );
```

## 最初のワークフロー

`Step`インターフェースを実装するステップハンドラーを定義します:

```php
use Queuety\Step;

class FetchDataHandler implements Step {
    public function handle( array $state ): array {
        $user = get_user_by( 'ID', $state['user_id'] );
        return [ 'user_name' => $user->display_name ];
    }

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

class CallLLMHandler implements Step {
    public function handle( array $state ): array {
        $response = wp_remote_post( 'https://api.openai.com/v1/chat/completions', [
            'body' => json_encode( [ 'prompt' => "Generate report for {$state['user_name']}" ] ),
        ] );
        return [ 'llm_response' => wp_remote_retrieve_body( $response ) ];
    }

    public function config(): array {
        return [ 'max_attempts' => 5 ];
    }
}

class FormatOutputHandler implements Step {
    public function handle( array $state ): array {
        $url = save_report( $state['user_name'], $state['llm_response'] );
        return [ 'report_url' => $url ];
    }

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

ワークフローをディスパッチします:

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

## ワーカーを起動する

```bash
wp queuety work
```

ワーカーは保留中のジョブをポーリングして実行し、ワークフローを進行させ、キューが空のときはスリープします。停止するには`Ctrl+C`を押します。ジョブの実行中であっても、プロセスは即座に終了します（[ワーカー](https://queuety.inline0.dev/ja/docs/features/workers#worker-lifecycle)を参照）。

上記の`SendEmailHandler`は`config()`を通じてジョブを`emails`キューに送るため、`default`上のワーカーはそれらを取得しません。使用するキューにはすべて名前を付けてください:

```bash
wp queuety work --queue=emails,default
```

専用ワーカーを実行しない場合でも、Queuetyには前述の毎分1回のデフォルトのWordPress cronフォールバックがあり、対象は`default`キューのみで、1回の実行につき1ジョブに限られます。専用ワーカーは、より高いスループットと低いレイテンシを実現します。

本番環境では、複数のワーカーを実行します:

```bash
wp queuety work --workers=4
```

優先順位を指定して複数のキューを処理します:

```bash
wp queuety work --queue=high,default,low
```

## 次のステップ

- 完全なディスパッチとハンドラーのガイドは[ジョブ](https://queuety.inline0.dev/ja/docs/jobs)を参照
- チェーン、並列ステップ、条件分岐、ワークフロー実行については[ワークフロー](https://queuety.inline0.dev/ja/docs/workflows)を参照
- レート制限、スロットリング、カスタムパイプラインロジックについては[ミドルウェア](https://queuety.inline0.dev/ja/docs/features/middleware)を参照
- コールバック付きのジョブグループのディスパッチについては[バッチ処理](https://queuety.inline0.dev/ja/docs/features/batching)を参照
- ストリーミングデータをチャンクごとに永続化する方法は[ストリーミングステップ](https://queuety.inline0.dev/ja/docs/workflows/streaming)を参照
- 繰り返し実行するジョブについては[スケジューリング](https://queuety.inline0.dev/ja/docs/features/scheduling)を参照
- プラグ可能なキャッシュレイヤーについては[キャッシュ](https://queuety.inline0.dev/ja/docs/features/caching)を参照
- QueueFakeとテストアサーションについては[テスト](https://queuety.inline0.dev/ja/docs/features/testing)を参照
- 利用可能なコマンド一覧は[CLIリファレンス](https://queuety.inline0.dev/ja/docs/cli)を参照
- プログラムからのアクセスについては[PHP API](https://queuety.inline0.dev/ja/docs/api)を参照
