
# キャッシュ

Queuetyには、キューの一時停止確認、レート制限カウンター、ワークフロー状態の参照、ロック操作など、頻繁に実行される処理でデータベースクエリを減らすキャッシュ層が含まれています。`Queuety::init()`を呼び出すと、キャッシュは自動的に初期化されます。

## キャッシュインターフェース

すべてのキャッシュバックエンドは`Queuety\Contracts\Cache`を実装します:

| メソッド | 戻り値 | 説明 |
|---|---|---|
| `get( string $key )` | `mixed` | 値を取得します。見つからない場合や期限切れの場合は`null`を返します。 |
| `set( string $key, mixed $value, int $ttl = 0 )` | `void` | 値を保存します。TTLが0の場合、期限切れになりません。 |
| `delete( string $key )` | `void` | 値を削除します。 |
| `has( string $key )` | `bool` | キーが存在し、期限切れでないかを確認します。 |
| `add( string $key, mixed $value, int $ttl = 0 )` | `bool` | キーがまだ存在しない場合にのみ値を設定します（アトミック）。値が設定された場合は`true`を返します。 |
| `flush()` | `void` | キャッシュ内のすべての項目を削除します。`ApcuCache::flush()`は`apcu_clear_cache()`を呼び出し、Queuetyのものだけでなく、サーバー上のすべてのAPCuエントリーを消去します。 |

## 組み込みバックエンド

### MemoryCache（デフォルト）

`Queuety\Cache\MemoryCache`は、プロセスごとの配列ベースのキャッシュです。項目はPHP配列に保存され、プロセスの終了時に失われます。APCuを利用できない場合のデフォルトバックエンドです。

拡張機能は不要で、単一ワーカーのデプロイに適しており、各ワーカープロセスは他のプロセスから分離されます。

### ApcuCache

`Queuety\Cache\ApcuCache`はAPCu拡張機能を使い、同じサーバー上のすべてのPHPプロセス間で共有メモリーを利用します。他のアプリケーションとの衝突を防ぐため、すべてのキーには`queuety:`が自動的に付加されます。

このバックエンドには`php-apcu`拡張機能が必要です。同じサーバー上のワーカー間でキャッシュエントリーを共有し、`add()`を`apcu_add()`経由で真にアトミックにします。

## 自動検出

`Queuety\Cache\CacheFactory`は、利用可能な最適なバックエンドを自動的に選択します:

`apcu_store()`が存在し、`apcu_enabled()`が`true`を返す場合、Queuetyは`ApcuCache`を使用します。それ以外の場合は`MemoryCache`にフォールバックします。これは`Queuety::init()`内で行われるため、デフォルトの動作に追加設定は不要です。

## キャッシュ対象

キャッシュ層は、複数のサブシステムで内部的に使用されます:

| データ | 用途 |
|---|---|
| キューの一時停止状態 | ワーカーのループごとにデータベースへ問い合わせるのを防ぎます |
| レート制限カウンター | 実行回数をデータベースではなくメモリーで追跡します |
| ワークフロー状態 | 複数ステップのワークフロー進行中の読み取りを減らします |
| ロック状態 | 一意のジョブとミューテックスミドルウェアでロックの有無を素早く確認できます |

## TTLの設定

デフォルトのキャッシュTTLは5秒です。キューの一時停止状態とレート制限カウンターに適用されます。ワークフローのステータスと状態の読み取りは固定の2秒間キャッシュされ、この時間は定数で変更できません。デフォルト値を変更するには、`wp-config.php`内の`QUEUETY_CACHE_TTL`定数を設定します:

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

TTLを短くするとデータベースへの問い合わせが増えますが、データは最新に保たれます。TTLを長くするとデータベースの負荷は減りますが、データの古さが増します。ほとんどのデプロイでは、デフォルトの5秒が適切なバランスです。

## カスタムキャッシュバックエンド

カスタムのキャッシュバックエンド（Redis、Memcachedなど）を使うには、`Contracts\Cache`インターフェースを実装し、`Queuety::init()`より前に`Queuety::set_cache()`を呼び出します:

```php
use Queuety\Contracts\Cache;
use Queuety\Queuety;

class RedisCache implements 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 { /* ... */ }
}

// Set the cache before init() so all subsystems use it.
Queuety::set_cache( new RedisCache() );
Queuety::init( $connection );
```

`set_cache()`を`init()`より前に呼び出すと、ファクトリーによる自動検出は完全にスキップされ、カスタムバックエンドが使用されます。

## キャッシュへのアクセス

いつでもアクティブなキャッシュインスタンスを取得できます:

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

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

現在アクティブなバックエンド（MemoryCache、ApcuCache、またはカスタム実装）が返されます。
