Readouble

Laravel 11.x キュー

イントロダクションIntroduction

Webアプリケーションの構築中に、アップロードされたCSVファイルの解析や保存など、通常のWebリクエスト中に実行するのでは時間がかかりすぎるタスクが発生する場合があります。幸運なことに、Laravelを使用すると、バックグラウンドで処理したい仕事をキューへ投入するジョブクラスが簡単に作成できます。時間のかかるタスクをキューに移動することで、アプリケーションはWebリクエストに驚異的な速度でレスポンスし、顧客により良いユーザーエクスペリエンスを提供できます。While building your web application, you may have some tasks, such as parsing and storing an uploaded CSV file, that take too long to perform during a typical web request. Thankfully, Laravel allows you to easily create queued jobs that may be processed in the background. By moving time intensive tasks to a queue, your application can respond to web requests with blazing speed and provide a better user experience to your customers.

Laravelキューは異なったキューバックエンド間に統一したキューのAPIを提供します。Amazon SQSRedis、もしくはリレーショナルデータベースでさえ使えます。Laravel queues provide a unified queueing API across a variety of different queue backends, such as Amazon SQS[https://aws.amazon.com/sqs/], Redis[https://redis.io], or even a relational database.

Laravelのキュー設定オプションは、アプリケーションのconfig/queue.php設定ファイルへ保存します。このファイルには、データベース、Amazon SQS, Redis, Beanstalkdドライバを含む、フレームワークが用意しているキュードライバの各接続設定が含まれています。また、キューに投入されたジョブを破棄する null キュードライバも含まれています。Laravel's queue configuration options are stored in your application's config/queue.php configuration file. In this file, you will find connection configurations for each of the queue drivers that are included with the framework, including the database, Amazon SQS[https://aws.amazon.com/sqs/], Redis[https://redis.io], and Beanstalkd[https://beanstalkd.github.io/] drivers, as well as a synchronous driver that will execute jobs immediately (for use during local development). A null queue driver is also included which discards queued jobs.

lightbulb Note: Laravelは、Redisを利用したキュー用の美しいダッシュボードと設定システムであるHorizo​​nも提供しています。詳細は、完全なHorizo​​nドキュメントを確認してください。[!NOTE]
Laravel now offers Horizon, a beautiful dashboard and configuration system for your Redis powered queues. Check out the full Horizon documentation[/docs/{{version}}/horizon] for more information.

接続 対 キューConnections vs. Queues

Laravelキューを使い始める前に、「接続」と「キュー」の違いを理解することが重要です。config/queue.php設定ファイルには、connections設定配列があります。このオプションは、Amazon SQS、Beanstalk、Redisなどのバックエンドキューサービスへの接続を定義します。ただし、特定のキュー接続には複数の「キュー」があり、キューに投入するジョブの異なるスタックまたはパイルと考えられます。Before getting started with Laravel queues, it is important to understand the distinction between "connections" and "queues". In your config/queue.php configuration file, there is a connections configuration array. This option defines the connections to backend queue services such as Amazon SQS, Beanstalk, or Redis. However, any given queue connection may have multiple "queues" which may be thought of as different stacks or piles of queued jobs.

queue設定ファイルの各接続設定例にはqueue属性が含まれていることに注意してください。これは、ジョブが特定の接続に送信されるときにジョブがディスパッチされるデフォルトのキューです。つまり、ディスパッチ先のキューを明示的に定義せずにジョブをディスパッチすると、ジョブは接続設定のqueue属性で定義されているキューへ配置されます。Note that each connection configuration example in the queue configuration file contains a queue attribute. This is the default queue that jobs will be dispatched to when they are sent to a given connection. In other words, if you dispatch a job without explicitly defining which queue it should be dispatched to, the job will be placed on the queue that is defined in the queue attribute of the connection configuration:

use App\Jobs\ProcessPodcast;

// このジョブは、デフォルト接続のデフォルトキューに送信される
ProcessPodcast::dispatch();

// このジョブは、デフォルトの接続の"emails"キューに送信される
ProcessPodcast::dispatch()->onQueue('emails');

あるアプリケーションでは、ジョブを複数のキューにプッシュする必要がなく、代わりに1つの単純なキューを使用するのが好まれるでしょう。しかし、ジョブを複数のキューにプッシュすることで、ジョブの処理方法に優先順位を付けたりセグメント化したりしたいアプリケーションで特に役立ちます。Laravelキューワーカは、優先度で処理するキューを指定できるためです。たとえば、ジョブを「高high」キューにプッシュする場合、より高い処理優先度を与えたワーカを実行します。Some applications may not need to ever push jobs onto multiple queues, instead preferring to have one simple queue. However, pushing jobs to multiple queues can be especially useful for applications that wish to prioritize or segment how jobs are processed, since the Laravel queue worker allows you to specify which queues it should process by priority. For example, if you push jobs to a high queue, you may run a worker that gives them higher processing priority:

php artisan queue:work --queue=high,default

ドライバの注意と事前要件Driver Notes and Prerequisites

データベースDatabase

databaseキュードライバを使用するには、ジョブを保持するデータベーステーブルが必要です。通常、これはLaravelのデフォルト0001_01_000002_create_jobs_table.php データベースマイグレーションに含まれていますが、アプリケーションにこのマイグレーションが含まれていない場合は、make:queue-table Artisanコマンドを使用して作成できます。In order to use the database queue driver, you will need a database table to hold the jobs. Typically, this is included in Laravel's default 0001_01_01_000002_create_jobs_table.php database migration[/docs/{{version}}/migrations]; however, if your application does not contain this migration, you may use the make:queue-table Artisan command to create it:

php artisan make:queue-table

php artisan migrate

RedisRedis

redisキュードライバを使用するには、config/database.php設定ファイルでRedisデータベース接続を設定する必要があります。In order to use the redis queue driver, you should configure a Redis database connection in your config/database.php configuration file.

warning Warning! redisキュードライバでは、serializercompression Redisオプションをサポートしていません。[!WARNING]
The serializer and compression Redis options are not supported by the redis queue driver.

RedisクラスタRedis Cluster

Redisキュー接続でRedisクラスタを使用する場合、キュー名にキーハッシュタグを含める必要があります。これは、特定のキューのすべてのRedisキーが同じハッシュスロットに配置されるようにするために必要です。If your Redis queue connection uses a Redis Cluster, your queue names must contain a key hash tag[https://redis.io/docs/reference/cluster-spec/#hash-tags]. This is required in order to ensure all of the Redis keys for a given queue are placed into the same hash slot:

'redis' => [
    'driver' => 'redis',
    'connection' => env('REDIS_QUEUE_CONNECTION', 'default'),
    'queue' => env('REDIS_QUEUE', '{default}'),
    'retry_after' => env('REDIS_QUEUE_RETRY_AFTER', 90),
    'block_for' => null,
    'after_commit' => false,
],

ブロッキングBlocking

Redisキューを使用する場合は、block_for設定オプションを使用して、ワーカループを反復処理し、Redisデータベースを再ポーリングする前に、ドライバがジョブが使用可能になるまで待機する時間を指定します。When using the Redis queue, you may use the block_for configuration option to specify how long the driver should wait for a job to become available before iterating through the worker loop and re-polling the Redis database.

キューの負荷に基づいてこの値を調整する方が、Redisデータベースを継続的にポーリングして新しいジョブを探すよりも効率的です。たとえば、値を「5」に設定して、ジョブが使用可能になるのを待つまで、ドライバが5秒間ブロックする必要があることを示すことができます。Adjusting this value based on your queue load can be more efficient than continually polling the Redis database for new jobs. For instance, you may set the value to 5 to indicate that the driver should block for five seconds while waiting for a job to become available:

'redis' => [
    'driver' => 'redis',
    'connection' => env('REDIS_QUEUE_CONNECTION', 'default'),
    'queue' => env('REDIS_QUEUE', 'default'),
    'retry_after' => env('REDIS_QUEUE_RETRY_AFTER', 90),
    'block_for' => 5,
    'after_commit' => false,
],

warning Warning! block_for0に設定すると、ジョブが使用可能になるまでキューワーカが無期限にブロックします。これにより、次のジョブが処理されるまで、SIGTERMなどのシグナルが処理されなくなります。[!WARNING]
Setting block_for to 0 will cause queue workers to block indefinitely until a job is available. This will also prevent signals such as SIGTERM from being handled until the next job has been processed.

その他のドライバの事前要件Other Driver Prerequisites

以下にリストしたキュードライバには、次の依存パッケージが必要です。これらの依存パッケージは、Composerパッケージマネージャを介してインストールできます。The following dependencies are needed for the listed queue drivers. These dependencies may be installed via the Composer package manager:

  • Amazon SQS: aws/aws-sdk-php ~3.0Amazon SQS: aws/aws-sdk-php ~3.0
  • Beanstalkd: pda/pheanstalk ~5.0Beanstalkd: pda/pheanstalk ~5.0
  • Redis: predis/predis ~2.0 or phpredis PHP extensionRedis: predis/predis ~2.0 or phpredis PHP extension
  • MongoDB: mongodb/laravel-mongodbMongoDB[https://www.mongodb.com/docs/drivers/php/laravel-mongodb/current/queues/]: mongodb/laravel-mongodb

ジョブの生成Creating Jobs

ジョブクラスの生成Generating Job Classes

デフォルトでは、アプリケーションのすべてのqueueableジョブは、app/Jobsディレクトリに保存します。app/Jobsディレクトリが存在しない場合でも、make:job Artisanコマンドを実行すると作成されます。By default, all of the queueable jobs for your application are stored in the app/Jobs directory. If the app/Jobs directory doesn't exist, it will be created when you run the make:job Artisan command:

php artisan make:job ProcessPodcast

生成されたクラスはIlluminate\Contracts\Queue\ShouldQueueインターフェイスを実装し、そのジョブをキューに投入する必要があり、非同期で実行することをLaravelに示します。The generated class will implement the Illuminate\Contracts\Queue\ShouldQueue interface, indicating to Laravel that the job should be pushed onto the queue to run asynchronously.

lightbulb Note: ジョブスタブはスタブのリソース公開を使用してカスタマイズできます[!NOTE]
Job stubs may be customized using stub publishing[/docs/{{version}}/artisan#stub-customization].

クラスの構造Class Structure

ジョブクラスは非常に単純で、ジョブがキューにより処理されるときに通常呼び出すhandleメソッドのみを持ちます。手始めに、ジョブクラスの例を見てみましょう。この例では、ポッドキャスト公開サービスを管理していて、アップロードされたポッドキャストファイルを公開する前に必要な処理があるのだと仮定してください。Job classes are very simple, normally containing only a handle method that is invoked when the job is processed by the queue. To get started, let's take a look at an example job class. In this example, we'll pretend we manage a podcast publishing service and need to process the uploaded podcast files before they are published:

<?php

namespace App\Jobs;

use App\Models\Podcast;
use App\Services\AudioProcessor;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;

class ProcessPodcast implements ShouldQueue
{
    use Queueable;

    /**
     * 新しいジョブインスタンスの生成
     */
    public function __construct(
        public Podcast $podcast,
    ) {}

    /**
     * ジョブの実行
     */
    public function handle(AudioProcessor $processor): void
    {
        // アップロードされたポッドキャストを処理…
    }
}

この例では、Eloquentモデルをキュー投入するジョブのコンストラクタへ直接渡すことができたことに注意してください。ジョブが使用しているQueueableトレイトにより、Eloquentモデルとそれらのロード済みリレーションは、ジョブの処理時に正常にシリアル化および非シリアル化されます。In this example, note that we were able to pass an Eloquent model[/docs/{{version}}/eloquent] directly into the queued job's constructor. Because of the Queueable trait that the job is using, Eloquent models and their loaded relationships will be gracefully serialized and unserialized when the job is processing.

キュー投入するジョブがコンストラクタでEloquentモデルを受け入れる場合、モデルの識別子のみがキューにシリアル化されます。ジョブが実際に処理されると、キューシステムは、完全なモデルインスタンスとそのロード済みリレーションをデータベースから自動的に再取得します。モデルのシリアル化に対するこのアプローチにより、はるかに小さなジョブペイロードをキュードライバに送信できます。If your queued job accepts an Eloquent model in its constructor, only the identifier for the model will be serialized onto the queue. When the job is actually handled, the queue system will automatically re-retrieve the full model instance and its loaded relationships from the database. This approach to model serialization allows for much smaller job payloads to be sent to your queue driver.

handleメソッドの依存注入handle Method Dependency Injection

handleメソッドは、ジョブがキューにより処理されるときに呼び出されます。そのジョブのhandleメソッドで依存関係をタイプヒントできることに注意してください。Laravelサービスコンテナは、これらの依存関係を自動的に依存注入します。The handle method is invoked when the job is processed by the queue. Note that we are able to type-hint dependencies on the handle method of the job. The Laravel service container[/docs/{{version}}/container] automatically injects these dependencies.

コンテナが依存関係をhandleメソッドへ依存注入する方法を完全に制御したい場合は、コンテナのbindMethodメソッドを使用します。bindMethodメソッドは、ジョブとコンテナを受け取るコールバックを受け入れます。コールバック内で、必要に応じてhandleメソッドを自由に呼び出すことができます。通常、このメソッドは、App\Providers\AppServiceProviderサービスプロバイダbootメソッドから呼び出す必要があります。If you would like to take total control over how the container injects dependencies into the handle method, you may use the container's bindMethod method. The bindMethod method accepts a callback which receives the job and the container. Within the callback, you are free to invoke the handle method however you wish. Typically, you should call this method from the boot method of your App\Providers\AppServiceProvider service provider[/docs/{{version}}/providers]:

use App\Jobs\ProcessPodcast;
use App\Services\AudioProcessor;
use Illuminate\Contracts\Foundation\Application;

$this->app->bindMethod([ProcessPodcast::class, 'handle'], function (ProcessPodcast $job, Application $app) {
    return $job->handle($app->make(AudioProcessor::class));
});

warning Warning! 素の画像の内容などのバイナリデータは、キュー投入するジョブへ渡す前に、base64_encode関数を介して渡す必要があります。そうしないと、ジョブがキューに配置されたときにJSONへ適切にシリアル化されない可能性があります。[!WARNING]
Binary data, such as raw image contents, should be passed through the base64_encode function before being passed to a queued job. Otherwise, the job may not properly serialize to JSON when being placed on the queue.

リレーションのキュー投入Queued Relationships

ロード済みのEloquentモデルリレーションはすべて、ジョブをキューに投入したときにシリアライズされるため、シリアライズしたジョブの文字列は非常に大きくなることがあります。さらに、ジョブがデシリアライズされ、モデルのリレーションがデータベースから再取得されるときには、こうした情報を完全に取得します。ジョブキューの処理中にモデルをシリアライズする前に適用されていたリレーションの制約は、そのジョブをデシリアライズするときに適用されません。したがって、特定のリレーションシップのサブセットを操作したい場合は、キューイングするジョブ内でそのリレーションを再制約する必要があります。Because all loaded Eloquent model relationships also get serialized when a job is queued, the serialized job string can sometimes become quite large. Furthermore, when a job is deserialized and model relationships are re-retrieved from the database, they will be retrieved in their entirety. Any previous relationship constraints that were applied before the model was serialized during the job queueing process will not be applied when the job is deserialized. Therefore, if you wish to work with a subset of a given relationship, you should re-constrain that relationship within your queued job.

もしくは、リレーションをシリアライズされないようにするため、プロパティ値を設定するときにモデルのwithoutRelationsメソッドを呼び出すこともできます。このメソッドは、ロード済みのリレーションシップを除いたモデルのインスタンスを返します。Or, to prevent relations from being serialized, you can call the withoutRelations method on the model when setting a property value. This method will return an instance of the model without its loaded relationships:

/**
 * 新しいジョブインスタンスの生成
 */
public function __construct(
    Podcast $podcast,
) {
    $this->podcast = $podcast->withoutRelations();
}

PHPのコンストラクタ・プロパティ・プロモーションを使用していて、あるEloquentモデルでリレーションをシリアライズしないことを指定したい場合は、WithoutRelations属性を使用します:If you are using PHP constructor property promotion and would like to indicate that an Eloquent model should not have its relations serialized, you may use the WithoutRelations attribute:

use Illuminate\Queue\Attributes\WithoutRelations;

/**
 * 新しいジョブインスタンスの生成
 */
public function __construct(
    #[WithoutRelations]
    public Podcast $podcast,
) {}

ジョブが単一モデルの代わりに、Eloquentモデルのコレクションまたは配列を受け取った場合、そのコレクション内のモデルでは、ジョブがデシリアライズされて実行されるときにそれらのリレーションは復元されません。これは、大量のモデルを扱うジョブで過剰なリソース使用を防ぐためです。If a job receives a collection or array of Eloquent models instead of a single model, the models within that collection will not have their relationships restored when the job is deserialized and executed. This is to prevent excessive resource usage on jobs that deal with large numbers of models.

一意なジョブUnique Jobs

warning Warning! 一意なジョブには、ロックをサポートするキャッシュドライバが必要です。現在、memcachedredisdynamodbdatabasefilearrayキャッシュドライバはアトミックロックをサポートしています。また、一意なジョブの制約は、バッチ内のジョブには適用されません。[!WARNING]
Unique jobs require a cache driver that supports locks[/docs/{{version}}/cache#atomic-locks]. Currently, the memcached, redis, dynamodb, database, file, and array cache drivers support atomic locks. In addition, unique job constraints do not apply to jobs within batches.

特定のジョブの1つのインスタンスのみを確実にキューで常に存在させたい場合があります。これを行うには、ジョブクラスにShouldBeUniqueインターフェイスを実装します。このインターフェイスでは、クラスへ追加のメソッドを定義する必要はありません。Sometimes, you may want to ensure that only one instance of a specific job is on the queue at any point in time. You may do so by implementing the ShouldBeUnique interface on your job class. This interface does not require you to define any additional methods on your class:

<?php

use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Queue\ShouldBeUnique;

class UpdateSearchIndex implements ShouldQueue, ShouldBeUnique
{
    ...
}

上記の例では、UpdateSearchIndexジョブは一意になります。したがって、ジョブの別のインスタンスがすでにキューにあり、処理が完了していない場合、ジョブはディスパッチされません。In the example above, the UpdateSearchIndex job is unique. So, the job will not be dispatched if another instance of the job is already on the queue and has not finished processing.

場合によっては、ジョブを一意にする特定の「キー」を定義したり、それを超えるとジョブが一意でなくなるタイムアウトを指定したりすることができます。これを行うには、ジョブクラスでuniqueIdおよびuniqueForプロパティまたはメソッドを定義します。In certain cases, you may want to define a specific "key" that makes the job unique or you may want to specify a timeout beyond which the job no longer stays unique. To accomplish this, you may define uniqueId and uniqueFor properties or methods on your job class:

<?php

use App\Models\Product;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Queue\ShouldBeUnique;

class UpdateSearchIndex implements ShouldQueue, ShouldBeUnique
{
    /**
     * 製品インスタンス
     *
     * @var \App\Product
     */
    public $product;

    /**
     * ジョブの一意のロックが解放されるまでの秒数
     *
     * @var int
     */
    public $uniqueFor = 3600;

    /**
     * ジョブの一意IDの取得
     */
    public function uniqueId(): string
    {
        return $this->product->id;
    }
}

上記の例では、UpdateSearchIndexジョブは製品IDによって一意になります。したがって、同じ製品IDを持つジョブの新しいディスパッチは、既存のジョブが処理を完了するまで無視されます。さらに、既存のジョブが1時間以内に処理されない場合、一意のロックが解放され、同じ一意のキーを持つ別のジョブをキューにディスパッチできます。In the example above, the UpdateSearchIndex job is unique by a product ID. So, any new dispatches of the job with the same product ID will be ignored until the existing job has completed processing. In addition, if the existing job is not processed within one hour, the unique lock will be released and another job with the same unique key can be dispatched to the queue.

warning Warning! アプリケーションで複数のウェブサーバやコンテナからジョブをディスパッチする場合、すべてのサーバが同じセントラルキャッシュサーバと通信していることを確認し、Laravelがジョブをユニークであるかを正確に判定できるようにする必要があります。[!WARNING]
If your application dispatches jobs from multiple web servers or containers, you should ensure that all of your servers are communicating with the same central cache server so that Laravel can accurately determine if a job is unique.

処理が開始されるまでジョブを一意に保つKeeping Jobs Unique Until Processing Begins

ジョブが処理を完了した後、または再試行にすべて失敗した後、一意のジョブは「ロック解除」されるのがデフォルト動作です。ただし、ジョブが処理される直前にロックを解除したい場合もあるでしょう。これを実現するには、ジョブで「ShouldBeUnique契約ではなくShouldBeUniqueUntilProcessing契約を実装する必要があります。By default, unique jobs are "unlocked" after a job completes processing or fails all of its retry attempts. However, there may be situations where you would like your job to unlock immediately before it is processed. To accomplish this, your job should implement the ShouldBeUniqueUntilProcessing contract instead of the ShouldBeUnique contract:

<?php

use App\Models\Product;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing;

class UpdateSearchIndex implements ShouldQueue, ShouldBeUniqueUntilProcessing
{
    // ...
}

一意なジョブロックUnique Job Locks

ShouldBeUniqueジョブがディスパッチされると、裏でLaravelはuniqueIdキーを使用してロックを取得しようとします。ロックが取得されていない場合、ジョブはディスパッチされません。このロックは、ジョブが処理を完了するか、再試行にすべて失敗すると解放されます。Laravelはデフォルトのキャッシュドライバを使用してこのロックを取得するのがデフォルト動作です。ただし、ロックを取得するために別のドライバを使用する場合は、使用するキャッシュドライバを返すuniqueViaメソッドを定義します。Behind the scenes, when a ShouldBeUnique job is dispatched, Laravel attempts to acquire a lock[/docs/{{version}}/cache#atomic-locks] with the uniqueId key. If the lock is not acquired, the job is not dispatched. This lock is released when the job completes processing or fails all of its retry attempts. By default, Laravel will use the default cache driver to obtain this lock. However, if you wish to use another driver for acquiring the lock, you may define a uniqueVia method that returns the cache driver that should be used:

use Illuminate\Contracts\Cache\Repository;
use Illuminate\Support\Facades\Cache;

class UpdateSearchIndex implements ShouldQueue, ShouldBeUnique
{
    ...

    /**
     * 一意のジョブロックのキャッシュドライバを取得
     */
    public function uniqueVia(): Repository
    {
        return Cache::driver('redis');
    }
}

lightbulb Note: ジョブの同時処理を制限するだけでよい場合は、代わりにWithoutOverlappingジョブミドルウェアを使用してください。[!NOTE]
If you only need to limit the concurrent processing of a job, use the WithoutOverlapping[/docs/{{version}}/queues#preventing-job-overlaps] job middleware instead.

ジョブの暗号化Encrypted Jobs

Laravelでは、暗号化により、ジョブのデータのプライバシーと完全性を確保できます。これを始めるには、ジョブクラスへShouldBeEncryptedインターフェイスを追加するだけです。このインターフェイスがクラスへ追加されると、Laravelはジョブをキューにプッシュする前に自動的に暗号化します。Laravel allows you to ensure the privacy and integrity of a job's data via encryption[/docs/{{version}}/encryption]. To get started, simply add the ShouldBeEncrypted interface to the job class. Once this interface has been added to the class, Laravel will automatically encrypt your job before pushing it onto a queue:

<?php

use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;

class UpdateSearchIndex implements ShouldQueue, ShouldBeEncrypted
{
    // ...
}

ジョブミドルウェアJob Middleware

ジョブミドルウェアを使用すると、キュー投入するジョブの実行にカスタムロジックをラップして、ジョブ自体の定型コードを減らせます。例として、LaravelのRedisレート制限機能を利用して、5秒ごとに1つのジョブのみを処理できるようにする次の「handle」メソッドを考えてみましょう。Job middleware allow you to wrap custom logic around the execution of queued jobs, reducing boilerplate in the jobs themselves. For example, consider the following handle method which leverages Laravel's Redis rate limiting features to allow only one job to process every five seconds:

use Illuminate\Support\Facades\Redis;

/**
 * ジョブの実行
 */
public function handle(): void
{
    Redis::throttle('key')->block(0)->allow(1)->every(5)->then(function () {
        info('Lock obtained...');

        // ジョブを処理…
    }, function () {
        // ロックの取得失敗

        return $this->release(5);
    });
}

このコードは有効ですが、handleメソッドの実装は、Redisのレート制限ロジックが散らかっているため、ノイズが多くなります。さらに、このレート制限ロジックは、レート制限する他のジョブでも重複。While this code is valid, the implementation of the handle method becomes noisy since it is cluttered with Redis rate limiting logic. In addition, this rate limiting logic must be duplicated for any other jobs that we want to rate limit.

handleメソッドでレート制限を行う代わりに、レート制限を処理するジョブミドルウェアを定義できます。Laravelにはジョブミドルウェアのデフォルトの場所が存在ないため、アプリケーションのどこにでもジョブミドルウェアを配置できます。この例では、ミドルウェアをapp/Jobs/Middlewareディレクトリに配置します。Instead of rate limiting in the handle method, we could define a job middleware that handles rate limiting. Laravel does not have a default location for job middleware, so you are welcome to place job middleware anywhere in your application. In this example, we will place the middleware in an app/Jobs/Middleware directory:

<?php

namespace App\Jobs\Middleware;

use Closure;
use Illuminate\Support\Facades\Redis;

class RateLimited
{
    /**
     * キュー投入したジョブの処理
     *
     * @param  \Closure(object): void  $next
     */
    public function handle(object $job, Closure $next): void
    {
        Redis::throttle('key')
                ->block(0)->allow(1)->every(5)
                ->then(function () use ($job, $next) {
                    // ロック取得

                    $next($job);
                }, function () use ($job) {
                    // ロックの取得失敗

                    $job->release(5);
                });
    }
}

ご覧のとおり、routeミドルウェアのように、ジョブミドルウェアは処理中のジョブと、ジョブの処理を続行するために呼び出す必要のあるコールバックを受け取ります。As you can see, like route middleware[/docs/{{version}}/middleware], job middleware receive the job being processed and a callback that should be invoked to continue processing the job.

ジョブミドルウェアを作成したら、ジョブのmiddlewareメソッドから返すことで、ジョブにアタッチできます。このメソッドは、make:job Artisanコマンドによってスカフォールドされたジョブには存在しないため、手作業でジョブクラスへ追加する必要があります。After creating job middleware, they may be attached to a job by returning them from the job's middleware method. This method does not exist on jobs scaffolded by the make:job Artisan command, so you will need to manually add it to your job class:

use App\Jobs\Middleware\RateLimited;

/**
 * このジョブを通過させるミドルウェアを取得
 *
 * @return array<int, object>
 */
public function middleware(): array
{
    return [new RateLimited];
}

lightbulb Note: Jobミドルウェアは、Queueableなイベントリスナ、Mailable、通知にも割り当てできます。[!NOTE]
Job middleware can also be assigned to queueable event listeners, mailables, and notifications.

レート制限Rate Limiting

独自のレート制限ジョブミドルウェアを作成する方法を示したばかりですが、実際には、Laravelはレート制限ジョブに利用できるレート制限ミドルウェアが含まれています。ルートのレートリミッタと同様に、ジョブのレートリミッタはRateLimiterファサードのforメソッドを使用して定義します。Although we just demonstrated how to write your own rate limiting job middleware, Laravel actually includes a rate limiting middleware that you may utilize to rate limit jobs. Like route rate limiters[/docs/{{version}}/routing#defining-rate-limiters], job rate limiters are defined using the RateLimiter facade's for method.

たとえば、プレミアム顧客には制限を課さずに、一般ユーザーには1時間に1回データをバックアップできるようにしたい場合があると思います。これを実現するには、AppServiceProviderbootメソッドでRateLimiterを定義します。For example, you may wish to allow users to backup their data once per hour while imposing no such limit on premium customers. To accomplish this, you may define a RateLimiter in the boot method of your AppServiceProvider:

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

/**
 * 全アプリケーションサービスの初期起動処理
 */
public function boot(): void
{
    RateLimiter::for('backups', function (object $job) {
        return $job->user->vipCustomer()
                    ? Limit::none()
                    : Limit::perHour(1)->by($job->user->id);
    });
}

上記の例では、1時間ごとのレート制限を定義しました。しかし、perMinuteメソッドを使用して、分に基づいたレート制限も簡単に定義できます。さらに、レート制限のbyメソッドへ任意の値を渡せます。この値は、顧客ごとにレート制限をセグメント化するために最もよく使用されます。In the example above, we defined an hourly rate limit; however, you may easily define a rate limit based on minutes using the perMinute method. In addition, you may pass any value you wish to the by method of the rate limit; however, this value is most often used to segment rate limits by customer:

return Limit::perMinute(50)->by($job->user->id);

レート制限を定義したら、Illuminate\Queue\Middleware\RateLimitedミドルウェアを使用してレートリミッターをジョブにアタッチできます。ジョブがレート制限を超えるたびに、このミドルウェアは、レート制限期間に基づいて適切な遅延でジョブをキューに戻します。Once you have defined your rate limit, you may attach the rate limiter to your job using the Illuminate\Queue\Middleware\RateLimited middleware. Each time the job exceeds the rate limit, this middleware will release the job back to the queue with an appropriate delay based on the rate limit duration.

use Illuminate\Queue\Middleware\RateLimited;

/**
 * このジョブを通過させるミドルウェアを取得
 *
 * @return array<int, object>
 */
public function middleware(): array
{
    return [new RateLimited('backups')];
}

レート制限したジョブをキューに戻すと、ジョブの「試行attempts」の総数は増加します。それに応じて、ジョブクラスのtriesプロパティとmaxExceptionsプロパティを調整することをお勧めします。または、retryUntilメソッドを使用して、ジョブが試行されなくなるまでの時間を定義することもできます。Releasing a rate limited job back onto the queue will still increment the job's total number of attempts. You may wish to tune your tries and maxExceptions properties on your job class accordingly. Or, you may wish to use the retryUntil method[#time-based-attempts] to define the amount of time until the job should no longer be attempted.

レート制限されているときにジョブを再試行させたくない場合は、dontReleaseメソッドを使用します。If you do not want a job to be retried when it is rate limited, you may use the dontRelease method:

/**
 * このジョブを通過させるミドルウェアを取得
 *
 * @return array<int, object>
 */
public function middleware(): array
{
    return [(new RateLimited('backups'))->dontRelease()];
}

lightbulb Note: Redisを使用している場合は、Illuminate\Queue\Middleware\RateLimitedWithRedisミドルウェアを使用できます。これは、Redis用に微調整されており、基本的なレート制限ミドルウェアよりも効率的です。[!NOTE]
If you are using Redis, you may use the Illuminate\Queue\Middleware\RateLimitedWithRedis middleware, which is fine-tuned for Redis and more efficient than the basic rate limiting middleware.

ジョブのオーバーラップの防止Preventing Job Overlaps

Laravelには、任意のキーに基づいてジョブの重複を防ぐことができるIlluminate\Queue\Middleware\WithoutOverlappingミドルウェアが含まれています。これは、キュー投入したジョブが、一度に1つのジョブによってのみ変更する必要があるリソースを変更している場合に役立ちます。Laravel includes an Illuminate\Queue\Middleware\WithoutOverlapping middleware that allows you to prevent job overlaps based on an arbitrary key. This can be helpful when a queued job is modifying a resource that should only be modified by one job at a time.

たとえば、ユーザーのクレジットスコアを更新するキュー投入するジョブがあり、同じユーザーIDのクレジットスコア更新ジョブが重複しないようにしたいとします。これを実現するには、ジョブのmiddlewareメソッドでWithoutOverlappingミドルウェアを返してください。For example, let's imagine you have a queued job that updates a user's credit score and you want to prevent credit score update job overlaps for the same user ID. To accomplish this, you can return the WithoutOverlapping middleware from your job's middleware method:

use Illuminate\Queue\Middleware\WithoutOverlapping;

/**
 * このジョブを通過させるミドルウェアを取得
 *
 * @return array<int, object>
 */
public function middleware(): array
{
    return [new WithoutOverlapping($this->user->id)];
}

同じタイプの重複するジョブはすべてキューに戻されます。リリースしたジョブが再試行するまでに経過する必要のある秒数を指定することもできます。Any overlapping jobs of the same type will be released back to the queue. You may also specify the number of seconds that must elapse before the released job will be attempted again:

/**
 * このジョブを通過させるミドルウェアを取得
 *
 * @return array<int, object>
 */
public function middleware(): array
{
    return [(new WithoutOverlapping($this->order->id))->releaseAfter(60)];
}

重複するジョブをすぐに削除して再試行しないようにする場合は、dontReleaseメソッドを使用します。If you wish to immediately delete any overlapping jobs so that they will not be retried, you may use the dontRelease method:

/**
 * このジョブを通過させるミドルウェアを取得
 *
 * @return array<int, object>
 */
public function middleware(): array
{
    return [(new WithoutOverlapping($this->order->id))->dontRelease()];
}

WithoutOverlappingミドルウェアはLaravelのアトミックロック機能により動作します。時々、ジョブは予期せずに失敗したり、ロックが解放されないような原因でタイムアウトしたりすることがあります。そのため、expireAfterメソッドを使用して、ロックの有効期限を明示的に定義することができます。たとえば、以下の例では、ジョブが処理を開始してから3分後にWithoutOverlappingロックを解除するようにLaravelへ指示します。The WithoutOverlapping middleware is powered by Laravel's atomic lock feature. Sometimes, your job may unexpectedly fail or timeout in such a way that the lock is not released. Therefore, you may explicitly define a lock expiration time using the expireAfter method. For example, the example below will instruct Laravel to release the WithoutOverlapping lock three minutes after the job has started processing:

/**
 * このジョブを通過させるミドルウェアを取得
 *
 * @return array<int, object>
 */
public function middleware(): array
{
    return [(new WithoutOverlapping($this->order->id))->expireAfter(180)];
}

warning Warning! WithoutOverlappingミドルウェアには、ロックをサポートするキャッシュドライバが必要です。現在、memcachedredisdynamodbdatabasefilearrayキャッシュドライバはアトミックロックをサポートしています。[!WARNING]
The WithoutOverlapping middleware requires a cache driver that supports locks[/docs/{{version}}/cache#atomic-locks]. Currently, the memcached, redis, dynamodb, database, file, and array cache drivers support atomic locks.

ジョブクラス間のロックキーの共用Sharing Lock Keys Across Job Classes

デフォルトのWithoutOverlappingミドルウェアは、同じクラスのジョブの重複を防ぐだけです。そのため、2つの異なるジョブクラスが同じロックキーを使用しても、重なり合うことは防げません。しかし、sharedメソッドを使用することで、ジョブクラス間でキーを共有するように、Laravelへ指示できます。By default, the WithoutOverlapping middleware will only prevent overlapping jobs of the same class. So, although two different job classes may use the same lock key, they will not be prevented from overlapping. However, you can instruct Laravel to apply the key across job classes using the shared method:

use Illuminate\Queue\Middleware\WithoutOverlapping;

class ProviderIsDown
{
    // ...

    public function middleware(): array
    {
        return [
            (new WithoutOverlapping("status:{$this->provider}"))->shared(),
        ];
    }
}

class ProviderIsUp
{
    // ...

    public function middleware(): array
    {
        return [
            (new WithoutOverlapping("status:{$this->provider}"))->shared(),
        ];
    }
}

例外による利用制限Throttling Exceptions

Laravelは、例外をスロットルすることができるIlluminate\Queue\Middleware\ThrottlesExceptionsミドルウェアを用意しています。ジョブが指定した回数の例外を投げると、それ以降のジョブの実行は指定時間間隔が経過するまで延期されます。このミドルウェアは、不安定なサードパーティのサービスとやり取りするジョブで特に有効です。Laravel includes a Illuminate\Queue\Middleware\ThrottlesExceptions middleware that allows you to throttle exceptions. Once the job throws a given number of exceptions, all further attempts to execute the job are delayed until a specified time interval lapses. This middleware is particularly useful for jobs that interact with third-party services that are unstable.

例えば、キュー投入したジョブがサードパーティのAPIとやりとりして、例外を投げるようになったとします。例外をスロットルするには、ジョブの middleware メソッドからThrottlesExceptionsというミドルウェアを返します。通常、このミドルウェアは、時間ベースの試行を実装したジョブと組み合わせて使用します。For example, let's imagine a queued job that interacts with a third-party API that begins throwing exceptions. To throttle exceptions, you can return the ThrottlesExceptions middleware from your job's middleware method. Typically, this middleware should be paired with a job that implements time based attempts[#time-based-attempts]:

use DateTime;
use Illuminate\Queue\Middleware\ThrottlesExceptions;

/**
 * このジョブを通過させるミドルウェアを取得
 *
 * @return array<int, object>
 */
public function middleware(): array
{
    return [new ThrottlesExceptions(10, 5 * 60)];
}

/**
 * ジョブがタイムアウトする時間を決定
 */
public function retryUntil(): DateTime
{
    return now()->addMinutes(30);
}

このミドルウェアが受け付ける最初のコンストラクタ引数は、スロットルされる前にジョブが投げられる例外の数で、2番目のコンストラクタ引数は、ジョブがスロットルされた後に再度施行するまでの秒数です。上のコード例では、ジョブが連続して10回の例外を投げた場合、30分の時間制限の制約を受けながら、ジョブを再試行する前に5分待ちます。The first constructor argument accepted by the middleware is the number of exceptions the job can throw before being throttled, while the second constructor argument is the number of seconds that should elapse before the job is attempted again once it has been throttled. In the code example above, if the job throws 10 consecutive exceptions, we will wait 5 minutes before attempting the job again, constrained by the 30-minute time limit.

ジョブが例外を投げ、例外のしきい値にまだ達していない場合、ジョブは通常すぐに再試行されます。ただし、ミドルウェアをジョブに接続するときに、backoffメソッドを呼び出すことで、ジョブを遅らせる必要がある数分を指定できます。When a job throws an exception but the exception threshold has not yet been reached, the job will typically be retried immediately. However, you may specify the number of minutes such a job should be delayed by calling the backoff method when attaching the middleware to the job:

use Illuminate\Queue\Middleware\ThrottlesExceptions;

/**
 * このジョブを通過させるミドルウェアを取得
 *
 * @return array<int, object>
 */
public function middleware(): array
{
    return [(new ThrottlesExceptions(10, 5 * 60))->backoff(5)];
}

内部的には、このミドルウェアはLaravelのキャッシュシステムを使用してレート制限を実装し、ジョブのクラス名をキャッシュ「キー」として利用します。ジョブにミドルウェアを添付するときにbyメソッドを呼び出し、このキーを上書きできます。これは、同じサードパーティのサービスと対話するジョブが複数のジョブを持っている場合に役立ち、それらに共通のスロットル「バケット」を共有できます。Internally, this middleware uses Laravel's cache system to implement rate limiting, and the job's class name is utilized as the cache "key". You may override this key by calling the by method when attaching the middleware to your job. This may be useful if you have multiple jobs interacting with the same third-party service and you would like them to share a common throttling "bucket":

use Illuminate\Queue\Middleware\ThrottlesExceptions;

/**
 * このジョブを通過させるミドルウェアを取得
 *
 * @return array<int, object>
 */
public function middleware(): array
{
    return [(new ThrottlesExceptions(10, 10 * 60))->by('key')];
}

このミドルウェアはデフォルトで、すべての例外をスロットル処理します。このミドルウェアをジョブへ指定するときに、whenメソッドを呼び出し、この動作を変更できます。この場合、whenメソッドで指定するクロージャが、trueを返した場合のみ、その例外をスロットルします。By default, this middleware will throttle every exception. You can modify this behaviour by invoking the when method when attaching the middleware to your job. The exception will then only be throttled if closure provided to the when method returns true:

use Illuminate\Http\Client\HttpClientException;
use Illuminate\Queue\Middleware\ThrottlesExceptions;

/**
 * ジョブを通過させるミドルウェアを取得
 *
 * @return array<int, object>
 */
public function middleware(): array
{
    return [(new ThrottlesExceptions(10, 10 * 60))->when(
        fn (Throwable $throwable) => $throwable instanceof HttpClientException
    )];
}

スロットルした例外をアプリケーションの例外ハンドラへ報告させたい場合は、ミドルウェアをジョブへ指定するときに、reportメソッドを呼び出してください。reportめそっどのオプションとしてクロージャを指定でき、その指定クロージャがtrueを返した場合にのみ例外を報告します。If you would like to have the throttled exceptions reported to your application's exception handler, you can do so by invoking the report method when attaching the middleware to your job. Optionally, you may provide a closure to the report method and the exception will only be reported if the given closure returns true:

use Illuminate\Http\Client\HttpClientException;
use Illuminate\Queue\Middleware\ThrottlesExceptions;

/**
 * ジョブを通過させるミドルウェアを取得
 *
 * @return array<int, object>
 */
public function middleware(): array
{
    return [(new ThrottlesExceptions(10, 10 * 60))->report(
        fn (Throwable $throwable) => $throwable instanceof HttpClientException
    )];
}

lightbulb Note: Redisを使用している場合は、Redis用に細かく調整され、基本的な例外スロットリングミドルウェアよりも効率的な、Illuminate\Queue\Middleware\ThrottlesExceptionsWithRedisミドルウェアを使用できます。[!NOTE]
If you are using Redis, you may use the Illuminate\Queue\Middleware\ThrottlesExceptionsWithRedis middleware, which is fine-tuned for Redis and more efficient than the basic exception throttling middleware.

ジョブのスキップSkipping Jobs

Skipミドルウェアを使うと、ジョブのロジックを変更せずに、ジョブをスキップ/削除するように指定できます。Skip::whenメソッドは指定条件をtrueと評価した場合にジョブを削除し、Skip::unlessメソッドは指定条件をfalseと評価した場合にジョブを削除します。The Skip middleware allows you to specify that a job should be skipped / deleted without needing to modify the job's logic. The Skip::when method will delete the job if the given condition evaluates to true, while the Skip::unless method will delete the job if the condition evaluates to false:

use Illuminate\Queue\Middleware\Skip;

/**
* ジョブを通過させるミドルウェアの取得
*/
public function middleware(): array
{
    return [
        Skip::when($someCondition),
    ];
}

また、whenメソッドとunlessメソッドへ、Closureを渡し、より複雑な条件判定を行うこともできます。You can also pass a Closure to the when and unless methods for more complex conditional evaluation:

use Illuminate\Queue\Middleware\Skip;

/**
* ジョブを通過させるミドルウェアの取得
*/
public function middleware(): array
{
    return [
        Skip::when(function (): bool {
            return $this->shouldSkip();
        }),
    ];
}

ジョブのディスパッチDispatching Jobs

ジョブクラスを作成したら、ジョブ自体でdispatchメソッドを使用してディスパッチできます。dispatchメソッドに渡した引数は、ジョブのコンストラクタに渡されます。Once you have written your job class, you may dispatch it using the dispatch method on the job itself. The arguments passed to the dispatch method will be given to the job's constructor:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Jobs\ProcessPodcast;
use App\Models\Podcast;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class PodcastController extends Controller
{
    /**
     * 新しいポッドキャストの保存
     */
    public function store(Request $request): RedirectResponse
    {
        $podcast = Podcast::create(/* ... */);

        // ...

        ProcessPodcast::dispatch($podcast);

        return redirect('/podcasts');
    }
}

条件付きでジョブをディスパッチする場合は、dispatchIfメソッドとdispatchUnlessメソッドが使用できます。If you would like to conditionally dispatch a job, you may use the dispatchIf and dispatchUnless methods:

ProcessPodcast::dispatchIf($accountActive, $podcast);

ProcessPodcast::dispatchUnless($accountSuspended, $podcast);

新しいLaravelアプリケーションでは、syncドライバがデフォルトのキュードライバです。このドライバは現在のリクエストをフォアグラウンドで同期的にジョブを実行し、たいていのローカル開発時では便利です。もし、バックグラウンド処理のために実際にキューを開始したい場合は、アプリケーションのconfig/queue.php設定ファイル内で、別のキュードライバを指定してください。In new Laravel applications, the sync driver is the default queue driver. This driver executes jobs synchronously in the foreground of the current request, which is often convenient during local development. If you would like to actually begin queueing jobs for background processing, you may specify a different queue driver within your application's config/queue.php configuration file.

ディスパッチの遅延Delayed Dispatching

ジョブをキューワーカによりすぐに処理できないように指定する場合は、ジョブをディスパッチするときにdelayメソッドを使用します。たとえば、ジョブがディスパッチされてから10分後まで処理にされないように指定してみましょう。If you would like to specify that a job should not be immediately available for processing by a queue worker, you may use the delay method when dispatching the job. For example, let's specify that a job should not be available for processing until 10 minutes after it has been dispatched:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Jobs\ProcessPodcast;
use App\Models\Podcast;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class PodcastController extends Controller
{
    /**
     * 新しいポッドキャストの保存
     */
    public function store(Request $request): RedirectResponse
    {
        $podcast = Podcast::create(/* ... */);

        // ...

        ProcessPodcast::dispatch($podcast)
                    ->delay(now()->addMinutes(10));

        return redirect('/podcasts');
    }
}

場合により、ジョブにはデフォルトの遅延が設定されていることがあります。この遅延を回避してジョブを即座にディスパッチしたい場合は、withoutDelayメソッドを使用します。In some cases, jobs may have a default delay configured. If you need to bypass this delay and dispatch a job for immediate processing, you may use the withoutDelay method:

ProcessPodcast::dispatch($podcast)->withoutDelay();

warning Warning! Amazon SQSキューサービスの最大遅延時間は15分です。[!WARNING]
The Amazon SQS queue service has a maximum delay time of 15 minutes.

レスポンスがブラウザに送信された後のディスパッチDispatching After the Response is Sent to the Browser

別の方法として、dispatchAfterResponseメソッドは、WebサーバでFastCGIを使っている場合、HTTPレスポンスがユーザーのブラウザへ送信されるまでジョブのディスパッチを遅らせます。これにより、キュー投入したジョブがまだ実行されている場合でも、ユーザーはアプリケーションの使用を開始できます。これは通常、電子メールの送信など、約1秒かかるジョブにのみ使用する必要があります。これは現在のHTTPリクエスト内で処理されるため、この方法でディスパッチされたジョブを処理するためにキューワーカを実行する必要はありません。Alternatively, the dispatchAfterResponse method delays dispatching a job until after the HTTP response is sent to the user's browser if your web server is using FastCGI. This will still allow the user to begin using the application even though a queued job is still executing. This should typically only be used for jobs that take about a second, such as sending an email. Since they are processed within the current HTTP request, jobs dispatched in this fashion do not require a queue worker to be running in order for them to be processed:

use App\Jobs\SendNotification;

SendNotification::dispatchAfterResponse();

クロージャを「ディスパッチdispatch」し、afterResponseメソッドをdispatchヘルパにチェーンしても、HTTPレスポンスがブラウザに送信された後にクロージャを実行できます。You may also dispatch a closure and chain the afterResponse method onto the dispatch helper to execute a closure after the HTTP response has been sent to the browser:

use App\Mail\WelcomeMessage;
use Illuminate\Support\Facades\Mail;

dispatch(function () {
    Mail::to('taylor@example.com')->send(new WelcomeMessage);
})->afterResponse();

同期ディスパッチSynchronous Dispatching

ジョブをすぐに(同期して)ディスパッチする場合は、dispatchSyncメソッドを使用します。この方法を使用する場合、ジョブはキューに入らず、現在のプロセス内ですぐに実行されます。If you would like to dispatch a job immediately (synchronously), you may use the dispatchSync method. When using this method, the job will not be queued and will be executed immediately within the current process:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Jobs\ProcessPodcast;
use App\Models\Podcast;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class PodcastController extends Controller
{
    /**
     * 新しいポッドキャストの保存
     */
    public function store(Request $request): RedirectResponse
    {
        $podcast = Podcast::create(/* ... */);

        // ポッドキャストの生成

        ProcessPodcast::dispatchSync($podcast);

        return redirect('/podcasts');
    }
}

ジョブとデータベーストランザクションJobs & Database Transactions

データベーストランザクション内でジョブをディスパッチすることはまったく問題ありませんが、実際にジョブが正常に実行できるよう特別な注意を払う必要があります。トランザクション内でジョブをディスパッチする場合、親トランザクションがコミットされる前にジョブがワーカによって処理される可能性があります。これが発生した場合、データベーストランザクション中にモデルまたはデータベースレコードに加えた更新は、データベースにまだ反映されていない可能性があります。さらに、トランザクション内で作成されたモデルまたはデータベースレコードは、データベースに存在しない可能性があります。While it is perfectly fine to dispatch jobs within database transactions, you should take special care to ensure that your job will actually be able to execute successfully. When dispatching a job within a transaction, it is possible that the job will be processed by a worker before the parent transaction has committed. When this happens, any updates you have made to models or database records during the database transaction(s) may not yet be reflected in the database. In addition, any models or database records created within the transaction(s) may not exist in the database.

幸いに、Laravelはこの問題を回避する方法をいくつか提供しています。まず、キュー接続の設定配列でafter_commit接続オプションを設定できます。Thankfully, Laravel provides several methods of working around this problem. First, you may set the after_commit connection option in your queue connection's configuration array:

'redis' => [
    'driver' => 'redis',
    // ...
    'after_commit' => true,
],

after_commitオプションがtrueの場合、データベーストランザクション内でジョブをディスパッチすることができます。ただし、Laravel は実際にジョブをディスパッチする前に、開いている親データベーストランザクションがコミットされるまで待機します。もちろん、現在開いているデータベーストランザクションがない場合は、ジョブはすぐにディスパッチされます。When the after_commit option is true, you may dispatch jobs within database transactions; however, Laravel will wait until the open parent database transactions have been committed before actually dispatching the job. Of course, if no database transactions are currently open, the job will be dispatched immediately.

トランザクション中に発生した例外によりロールバックされた場合、そのトランザクション中にディスパッチされたジョブは破棄されます。If a transaction is rolled back due to an exception that occurs during the transaction, the jobs that were dispatched during that transaction will be discarded.

lightbulb Note: after_commit設定オプションをtrueに設定すると、開いているすべてのデータベーストランザクションがコミットされた後、キュー投入したイベントリスナ、メーラブル、通知、およびブロードキャストイベントもディスパッチされます。[!NOTE]
Setting the after_commit configuration option to true will also cause any queued event listeners, mailables, notifications, and broadcast events to be dispatched after all open database transactions have been committed.

コミットディスパッチ動作をインラインで指定Specifying Commit Dispatch Behavior Inline

after_commitキュー接続設定オプションをtrueに設定しない場合でも、開いているすべてのデータベーストランザクションがコミットされた後に特定のジョブをディスパッチする必要があることを示すことができます。これを実現するには、afterCommitメソッドをディスパッチ操作にチェーンします。If you do not set the after_commit queue connection configuration option to true, you may still indicate that a specific job should be dispatched after all open database transactions have been committed. To accomplish this, you may chain the afterCommit method onto your dispatch operation:

use App\Jobs\ProcessPodcast;

ProcessPodcast::dispatch($podcast)->afterCommit();

同様に、after_commit設定オプションがtrueに設定されている場合でも、開いているデータベーストランザクションがコミットするのを待たずに、特定のジョブをすぐにディスパッチする必要があることを示すことができます。Likewise, if the after_commit configuration option is set to true, you may indicate that a specific job should be dispatched immediately without waiting for any open database transactions to commit:

ProcessPodcast::dispatch($podcast)->beforeCommit();

ジョブチェーンJob Chaining

ジョブチェーンを使用すると、プライマリジョブが正常に実行された後から順番に実行する必要があるキュー投入するジョブのリストを指定できます。シーケンス内の1つのジョブが失敗した場合は、残りのジョブを実行しません。キュー投入するジョブチェーンを実行するには、Busファサードが提供するchainメソッドを使用します。Laravelのコマンドバスは、キュー投入するジョブのディスパッチをその上で構築している、下位レベルのコンポーネントです。Job chaining allows you to specify a list of queued jobs that should be run in sequence after the primary job has executed successfully. If one job in the sequence fails, the rest of the jobs will not be run. To execute a queued job chain, you may use the chain method provided by the Bus facade. Laravel's command bus is a lower level component that queued job dispatching is built on top of:

use App\Jobs\OptimizePodcast;
use App\Jobs\ProcessPodcast;
use App\Jobs\ReleasePodcast;
use Illuminate\Support\Facades\Bus;

Bus::chain([
    new ProcessPodcast,
    new OptimizePodcast,
    new ReleasePodcast,
])->dispatch();

ジョブクラスインスタンスをチェーンすることに加えて、クロージャをチェーンすることもできます。In addition to chaining job class instances, you may also chain closures:

Bus::chain([
    new ProcessPodcast,
    new OptimizePodcast,
    function () {
        Podcast::update(/* ... */);
    },
])->dispatch();

warning Warning! ジョブ内で$this->delete()メソッドを使用してジョブを削除しても、チェーンしたジョブの処理が妨げられることはありません。チェーンは、チェーン内のジョブが失敗した場合にのみ実行を停止します。[!WARNING]
Deleting jobs using the $this->delete() method within the job will not prevent chained jobs from being processed. The chain will only stop executing if a job in the chain fails.

チェーン接続とキューChain Connection and Queue

チェーンジョブに使用する接続とキューを指定する場合は、onConnectionメソッドとonQueueメソッドを使用します。キュー投入する各ジョブに別の接続/キューが明示的に指定されない限り、これらのメソッドでチェーンに対し指定するキュー接続とキュー名を使用します。If you would like to specify the connection and queue that should be used for the chained jobs, you may use the onConnection and onQueue methods. These methods specify the queue connection and queue name that should be used unless the queued job is explicitly assigned a different connection / queue:

Bus::chain([
    new ProcessPodcast,
    new OptimizePodcast,
    new ReleasePodcast,
])->onConnection('redis')->onQueue('podcasts')->dispatch();

チェーンへのジョブ追加Adding Jobs to the Chain

時に、既存のジョブチェーンへ、そのチェーン内の別のジョブからジョブを追加する必要があるかもしれません。それにはprependToChainメソッドとappendToChainメソッドを使用してください。Occasionally, you may need to prepend or append a job to an existing job chain from within another job in that chain. You may accomplish this using the prependToChain and appendToChain methods:

/**
 * ジョブを実行
 */
public function handle(): void
{
    // ...

    // Prepend to the current chain, run job immediately after current job...
    $this->prependToChain(new TranscribePodcast);

    // Append to the current chain, run job at end of chain...
    $this->appendToChain(new TranscribePodcast);
}

チェーンの失敗Chain Failures

ジョブをチェーンする場合、catchメソッドを使用して、チェーン内のジョブが失敗した場合に呼び出すクロージャを指定できます。指定するコールバックは、ジョブの失敗の原因となったThrowableインスタンスを受け取ります。When chaining jobs, you may use the catch method to specify a closure that should be invoked if a job within the chain fails. The given callback will receive the Throwable instance that caused the job failure:

use Illuminate\Support\Facades\Bus;
use Throwable;

Bus::chain([
    new ProcessPodcast,
    new OptimizePodcast,
    new ReleasePodcast,
])->catch(function (Throwable $e) {
    // チェーン内のジョブが失敗
})->dispatch();

warning Warning! チェーンコールバックはシリアライズされ、Laravelのキューによって後ほど実行されるため、チェーンコールバック内で$this変数を使用するべきではありません。[!WARNING]
Since chain callbacks are serialized and executed at a later time by the Laravel queue, you should not use the $this variable within chain callbacks.

キューと接続のカスタマイズCustomizing the Queue and Connection

特定のキューへのディスパッチDispatching to a Particular Queue

ジョブを他のキューに投入することで、キュー投入したジョブを「分類」し、さまざまなキューに割り当てるワーカの数に優先度を付けることもできます。これは、キュー設定ファイルで定義している他のキュー「接続」にジョブを投入するのではなく、同じ接続内の特定のキューにのみプッシュすることに注意してください。キューを指定するには、ジョブをディスパッチするときにonQueueメソッドを使用します。By pushing jobs to different queues, you may "categorize" your queued jobs and even prioritize how many workers you assign to various queues. Keep in mind, this does not push jobs to different queue "connections" as defined by your queue configuration file, but only to specific queues within a single connection. To specify the queue, use the onQueue method when dispatching the job:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Jobs\ProcessPodcast;
use App\Models\Podcast;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class PodcastController extends Controller
{
    /**
     * 新しいポッドキャストの保存
     */
    public function store(Request $request): RedirectResponse
    {
        $podcast = Podcast::create(/* ... */);

        // ポッドキャストの生成

        ProcessPodcast::dispatch($podcast)->onQueue('processing');

        return redirect('/podcasts');
    }
}

または、ジョブのコンストラクタ内でonQueueメソッドを呼び出して、ジョブのキューを指定することもできます。Alternatively, you may specify the job's queue by calling the onQueue method within the job's constructor:

<?php

namespace App\Jobs;

 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Foundation\Queue\Queueable;

class ProcessPodcast implements ShouldQueue
{
    use Queueable;

    /**
     * 新しいジョブインスタンスの生成
     */
    public function __construct()
    {
        $this->onQueue('processing');
    }
}

特定の接続へのディスパッチDispatching to a Particular Connection

アプリケーションが複数のキュー接続と対話する場合は、onConnectionメソッドを使用してジョブをプッシュする接続を指定できます。If your application interacts with multiple queue connections, you may specify which connection to push a job to using the onConnection method:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Jobs\ProcessPodcast;
use App\Models\Podcast;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class PodcastController extends Controller
{
    /**
     * 新しいポッドキャストの保存
     */
    public function store(Request $request): RedirectResponse
    {
        $podcast = Podcast::create(/* ... */);

        // ポッドキャストの生成

        ProcessPodcast::dispatch($podcast)->onConnection('sqs');

        return redirect('/podcasts');
    }
}

onConnectionメソッドとonQueueメソッドをチェーンして、ジョブの接続とキューを指定できます。You may chain the onConnection and onQueue methods together to specify the connection and the queue for a job:

ProcessPodcast::dispatch($podcast)
              ->onConnection('sqs')
              ->onQueue('processing');

または、ジョブのコンストラクター内でonConnectionメソッドを呼び出すことにより、ジョブの接続を指定することもできます。Alternatively, you may specify the job's connection by calling the onConnection method within the job's constructor:

<?php

namespace App\Jobs;

 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Foundation\Queue\Queueable;

class ProcessPodcast implements ShouldQueue
{
    use Queueable;

    /**
     * 新しいジョブインスタンスの生成
     */
    public function __construct()
    {
        $this->onConnection('sqs');
    }
}

最大試行回数/タイムアウト値の指定Specifying Max Job Attempts / Timeout Values

最大試行回数Max Attempts

キュー投入したジョブの1つでエラーが発生した場合、そのジョブが無期限に再試行し続けることを普通は望まないでしょう。したがって、Laravelは、ジョブを試行できる回数または期間を指定するさまざまな方法を提供しています。If one of your queued jobs is encountering an error, you likely do not want it to keep retrying indefinitely. Therefore, Laravel provides various ways to specify how many times or for how long a job may be attempted.

ジョブを試行できる最大回数を指定する1つの方法は、Artisanコマンドラインの--triesスイッチを使用することです。これは、処理中のジョブへ試行回数を指定しない限り、ワーカが処理するすべてのジョブに適用します。One approach to specifying the maximum number of times a job may be attempted is via the --tries switch on the Artisan command line. This will apply to all jobs processed by the worker unless the job being processed specifies the number of times it may be attempted:

php artisan queue:work --tries=3

ジョブが最大試行回数を超えると、「失敗した」ジョブと見なされます。失敗したジョブの処理の詳細は、失敗したジョブのドキュメントを参照してください。queue:workコマンドで、--tries=0を指定した場合は、ジョブを無制限に再試行します。If a job exceeds its maximum number of attempts, it will be considered a "failed" job. For more information on handling failed jobs, consult the failed job documentation[#dealing-with-failed-jobs]. If --tries=0 is provided to the queue:work command, the job will be retried indefinitely.

ジョブクラス自体でジョブを試行できる最大回数を定義することで、より詳細なアプローチをとることもできます。ジョブで最大試行回数が指定されている場合、コマンドラインで指定する--tries値よりも優先されます。You may take a more granular approach by defining the maximum number of times a job may be attempted on the job class itself. If the maximum number of attempts is specified on the job, it will take precedence over the --tries value provided on the command line:

<?php

namespace App\Jobs;

class ProcessPodcast implements ShouldQueue
{
    /**
     * ジョブを試行する回数を決定
     *
     * @var int
     */
    public $tries = 5;
}

特定ジョブの最大試行回数を動的に制御する必要がある場合は、そのジョブにtriesメソッドを定義します。If you need dynamic control over a particular job's maximum attempts, you may define a tries method on the job:

/**
 * ジョブを試行する回数を決定
 */
public function tries(): int
{
    return 5;
}

時間ベースの試行Time Based Attempts

ジョブが失敗するまでに試行できる回数を定義する代わりに、ジョブをそれ以上実行しない時間を定義することもできます。これにより、特定の時間枠内でジョブを何度も試行できます。ジョブを試行しないタイムアウトを定義するには、ジョブクラスにretryUntilメソッドを追加します。このメソッドはDateTimeインスタンスを返す必要があります:As an alternative to defining how many times a job may be attempted before it fails, you may define a time at which the job should no longer be attempted. This allows a job to be attempted any number of times within a given time frame. To define the time at which a job should no longer be attempted, add a retryUntil method to your job class. This method should return a DateTime instance:

use DateTime;

/**
 * ジョブがタイムアウトする時間を決定
 */
public function retryUntil(): DateTime
{
    return now()->addMinutes(10);
}

lightbulb Note: キュー投入済みイベントリスナtriesプロパティまたはretryUntilメソッドを定義することもできます。[!NOTE]
You may also define a tries property or retryUntil method on your queued event listeners[/docs/{{version}}/events#queued-event-listeners].

最大例外数Max Exceptions

あるジョブを何度も試行してもよいが、所定の数の未処理の例外が発生した場合には失敗するように指定したい場合があるかもしれません。(releaseメソッドによって直接解放されるのではなく、所定の数の未処理の例外が発生した場合。)これを実現するには、ジョブクラスに maxExceptionsプロパティを定義します。Sometimes you may wish to specify that a job may be attempted many times, but should fail if the retries are triggered by a given number of unhandled exceptions (as opposed to being released by the release method directly). To accomplish this, you may define a maxExceptions property on your job class:

<?php

namespace App\Jobs;

use Illuminate\Support\Facades\Redis;

class ProcessPodcast implements ShouldQueue
{
    /**
     * ジョブを試行する回数を決定
     *
     * @var int
     */
    public $tries = 25;

    /**
     * 失敗する前に許可する未処理の例外の最大数
     *
     * @var int
     */
    public $maxExceptions = 3;

    /**
     * ジョブの実行
     */
    public function handle(): void
    {
        Redis::throttle('key')->allow(10)->every(60)->then(function () {
            // ロックを取得し、ポッドキャストを処理する
        }, function () {
            // ロックを獲得できなかった
            return $this->release(10);
        });
    }
}

この例では、アプリケーションがRedisロックを取得できない場合、ジョブは10秒間解放され、最大25回再試行され続けます。ただし、ジョブによって3つの未処理の例外がスローされると、ジョブは失敗します。In this example, the job is released for ten seconds if the application is unable to obtain a Redis lock and will continue to be retried up to 25 times. However, the job will fail if three unhandled exceptions are thrown by the job.

タイムアウトTimeout

多くの場合、キュー投入したジョブにかかると予想されるおおよその時間をあなたは知っています。このため、Laravelでは「タイムアウト」値も指定できます。デフォルトのタイムアウト値は60秒です。ジョブがタイムアウト値で指定する秒数より長く処理されている場合、ジョブを処理しているワーカはエラーで終了します。通常、ワーカはサーバで設定したプロセスマネージャによって自動的に再起動されます。Often, you know roughly how long you expect your queued jobs to take. For this reason, Laravel allows you to specify a "timeout" value. By default, the timeout value is 60 seconds. If a job is processing for longer than the number of seconds specified by the timeout value, the worker processing the job will exit with an error. Typically, the worker will be restarted automatically by a process manager configured on your server[#supervisor-configuration].

ジョブを実行できる最大秒数は、Artisanコマンドラインの--timeoutスイッチを使用して指定できます。The maximum number of seconds that jobs can run may be specified using the --timeout switch on the Artisan command line:

php artisan queue:work --timeout=30

ジョブが継続的にタイムアウトして最大試行回数を超えた場合、失敗としてマークされます。If the job exceeds its maximum attempts by continually timing out, it will be marked as failed.

また、ジョブクラス自体でジョブの実行を許可する最大秒数を定義することもできます。ジョブでタイムアウトが指定されている場合、コマンドラインで指定されているタイムアウトよりも優先されます。You may also define the maximum number of seconds a job should be allowed to run on the job class itself. If the timeout is specified on the job, it will take precedence over any timeout specified on the command line:

<?php

namespace App\Jobs;

class ProcessPodcast implements ShouldQueue
{
    /**
     * タイムアウトになる前にジョブを実行できる秒数
     *
     * @var int
     */
    public $timeout = 120;
}

ソケットや送信HTTP接続などのI/Oブロッキングプロセスが、指定するタイムアウトを尊重しない場合があります。したがって、これらの機能を使用するときは、常にAPIを使用してタイムアウトを指定するようにしてください。たとえば、Guzzleを使用する場合は、常に接続を指定し、タイムアウト値をリクエストする必要があります。Sometimes, IO blocking processes such as sockets or outgoing HTTP connections may not respect your specified timeout. Therefore, when using these features, you should always attempt to specify a timeout using their APIs as well. For example, when using Guzzle, you should always specify a connection and request timeout value.

warning Warning! ジョブのタイムアウトを指定するには、pcntl PHP拡張モジュールをインストールする必要があります。加えて、ジョブの"timeout"の値は、常に"retry after"値よりも小さい必要があります。そうしない場合、ジョブの実行が終了する前に再試行したり、タイムアウトしたりする可能性があります。[!WARNING]
The pcntl PHP extension must be installed in order to specify job timeouts. In addition, a job's "timeout" value should always be less than its "retry after"[#job-expiration] value. Otherwise, the job may be re-attempted before it has actually finished executing or timed out.

タイムアウトによる失敗Failing on Timeout

タイムアウトによるジョブの失敗をマークしたい場合は、ジョブクラスに$failOnTimeoutプロパティを定義します。If you would like to indicate that a job should be marked as failed[#dealing-with-failed-jobs] on timeout, you may define the $failOnTimeout property on the job class:

/**
 * ジョブがタイムアウトで失敗したとマークするかを指定
 *
 * @var bool
 */
public $failOnTimeout = true;

エラー処理Error Handling

ジョブの処理中に例外が投げられた場合、ジョブは自動的にキューへ解放されるため、再試行できます。ジョブは、アプリケーションで許可されている最大回数試行されるまで解放され続けます。最大試行回数は、queue:work Artisanコマンドで使用される--triesスイッチによって定義されます。または、最大試行回数をジョブクラス自体で定義することもできます。キューワーカの実行の詳細は、以下で見つかりますIf an exception is thrown while the job is being processed, the job will automatically be released back onto the queue so it may be attempted again. The job will continue to be released until it has been attempted the maximum number of times allowed by your application. The maximum number of attempts is defined by the --tries switch used on the queue:work Artisan command. Alternatively, the maximum number of attempts may be defined on the job class itself. More information on running the queue worker can be found below[#running-the-queue-worker].

手作業でジョブを解放Manually Releasing a Job

後で再試行できるように、ジョブを手作業でキューへ戻したい場合があります。これは、releaseメソッドを呼び出すことで実現できます。Sometimes you may wish to manually release a job back onto the queue so that it can be attempted again at a later time. You may accomplish this by calling the release method:

/**
 * ジョブの実行
 */
public function handle(): void
{
    // ...

    $this->release();
}

デフォルトでreleaseメソッドは、ジョブをキューに戻してすぐに処理できるようにします。しかし、releaseメソッドへ整数値または日付のインスタンスを渡すことにより、指定秒数が経過するまでジョブを処理しないように、キューへ指示できます:By default, the release method will release the job back onto the queue for immediate processing. However, you may instruct the queue to not make the job available for processing until a given number of seconds has elapsed by passing an integer or date instance to the release method:

$this->release(10);

$this->release(now()->addSeconds(10));

手作業でジョブを失敗させるManually Failing a Job

場合によっては、ジョブを「失敗した」として手作業でマークする必要があります。これには、failメソッドを呼び出してください。Occasionally you may need to manually mark a job as "failed". To do so, you may call the fail method:

/**
 * ジョブの実行
 */
public function handle(): void
{
    // ...

    $this->fail();
}

キャッチした例外が原因でジョブを失敗としてマークしたい場合は、その例外をfailメソッドへ渡せます。また、エラーメッセージを文字列で渡せば、例外に変換してくれるのも便利でしょう。If you would like to mark your job as failed because of an exception that you have caught, you may pass the exception to the fail method. Or, for convenience, you may pass a string error message which will be converted to an exception for you:

$this->fail($exception);

$this->fail('Something went wrong.');

lightbulb Note: 失敗したジョブの詳細は、ジョブの失敗の処理に関するドキュメントを確認してください。[!NOTE]
For more information on failed jobs, check out the documentation on dealing with job failures[#dealing-with-failed-jobs].

ジョブバッチJob Batching

Laravelのジョブバッチ機能は、ジョブのバッチ処理を簡単に実行し、ジョブのバッチが実行完了したときに何らかのアクションを実行できます。使い始める前に、ジョブバッチの完了率などのメタ情報を含むテーブルを構築するために、データベースマイグレーションを作成する必要があります。このマイグレーションはmake:queue-batches-table Artisanコマンドを使用して生成できます。Laravel's job batching feature allows you to easily execute a batch of jobs and then perform some action when the batch of jobs has completed executing. Before getting started, you should create a database migration to build a table which will contain meta information about your job batches, such as their completion percentage. This migration may be generated using the make:queue-batches-table Artisan command:

php artisan make:queue-batches-table

php artisan migrate

Batchableジョブの定義Defining Batchable Jobs

バッチ可能なジョブを定義するには、通常どおりキュー可能なジョブを作成する必要があります。ただし、ジョブクラスにIlluminate\Bus\Batchableトレイトを追加する必要があります。このトレイトは、ジョブを実行している現在のバッチを取得するために使用するbatchメソッドへのアクセスを提供します。To define a batchable job, you should create a queueable job[#creating-jobs] as normal; however, you should add the Illuminate\Bus\Batchable trait to the job class. This trait provides access to a batch method which may be used to retrieve the current batch that the job is executing within:

<?php

namespace App\Jobs;

use Illuminate\Bus\Batchable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;

class ImportCsv implements ShouldQueue
{
    use Batchable, Queueable;

    /**
     * ジョブの実行
     */
    public function handle(): void
    {
        if ($this->batch()->cancelled()) {
            // バッチがキャンセルされたかどうかを判定

            return;
        }

        // CSVファイルの一部をインポート…
    }
}

バッチのディスパッチDispatching Batches

ジョブのバッチをディスパッチするには、Busファサードのbatchメソッドを使用する必要があります。もちろん、バッチ処理は、完了コールバックと組み合わせるとき、主に役立ちます。したがってthencatchfinallyメソッドを使用して、バッチの完了コールバックを定義できます。これらの各コールバックは、呼び出されたときにIlluminate\Bus\Batchインスタンスを受け取ります。以下の例では、CSVファイルから指定する数の行をそれぞれ処理するジョブのバッチをキューに入れていると仮定します。To dispatch a batch of jobs, you should use the batch method of the Bus facade. Of course, batching is primarily useful when combined with completion callbacks. So, you may use the then, catch, and finally methods to define completion callbacks for the batch. Each of these callbacks will receive an Illuminate\Bus\Batch instance when they are invoked. In this example, we will imagine we are queueing a batch of jobs that each process a given number of rows from a CSV file:

use App\Jobs\ImportCsv;
use Illuminate\Bus\Batch;
use Illuminate\Support\Facades\Bus;
use Throwable;

$batch = Bus::batch([
    new ImportCsv(1, 100),
    new ImportCsv(101, 200),
    new ImportCsv(201, 300),
    new ImportCsv(301, 400),
    new ImportCsv(401, 500),
])->before(function (Batch $batch) {
    // バッチは生成されたが、ジョブは追加されていない
})->progress(function (Batch $batch) {
    // 一つのジョブが正常に終了
})->then(function (Batch $batch) {
    // すべてのジョブが正常に完了
})->catch(function (Batch $batch, Throwable $e) {
    // バッチジョブの失敗をはじめて検出
})->finally(function (Batch $batch) {
    // バッチの実行が終了
})->dispatch();

return $batch->id;

バッチのIDは、$batch->idプロパティを介してアクセスでき、ディスパッチ後のバッチに関する情報をLaravelコマンドバスに照会するために使用できます。The batch's ID, which may be accessed via the $batch->id property, may be used to query the Laravel command bus[#inspecting-batches] for information about the batch after it has been dispatched.

warning Warning! バッチコールバックはシリアライズされ、Laravelのキューが後ほど実行するため、コールバック内で$this変数を使用すべきではありません。さらに、バッチジョブはデータベーストランザクション内へラップするため、暗黙のコミットを行うデータベースステートメントをジョブ内で実行しないでください。[!WARNING]
Since batch callbacks are serialized and executed at a later time by the Laravel queue, you should not use the $this variable within the callbacks. In addition, since batched jobs are wrapped within database transactions, database statements that trigger implicit commits should not be executed within the jobs.

名前付きバッチNaming Batches

LaravelHorizo​​nやLaravelTelescopeなどの一部のツールは、バッチに名前が付けられている場合、バッチのよりユーザーフレンドリーなデバッグ情報を提供します。バッチに任意の名前を割り当てるには、バッチを定義するときにnameメソッドを呼び出すことができます。Some tools such as Laravel Horizon and Laravel Telescope may provide more user-friendly debug information for batches if batches are named. To assign an arbitrary name to a batch, you may call the name method while defining the batch:

$batch = Bus::batch([
    // ...
])->then(function (Batch $batch) {
    // すべてのジョブが正常に完了
})->name('Import CSV')->dispatch();

バッチ接続とキューBatch Connection and Queue

バッチ処理されたジョブに使用する接続とキューを指定する場合は、onConnectionメソッドとonQueueメソッドを使用できます。バッチ処理するすべてのジョブは、同じ接続とキュー内で実行する必要があります。If you would like to specify the connection and queue that should be used for the batched jobs, you may use the onConnection and onQueue methods. All batched jobs must execute within the same connection and queue:

$batch = Bus::batch([
    // ...
])->then(function (Batch $batch) {
    // すべてのジョブが正常に完了
})->onConnection('redis')->onQueue('imports')->dispatch();

チェーンとバッチChains and Batches

配列内に配置することにより、バッチ内で一連のジョブチェーンを定義できます。たとえば、2つのジョブチェーンを並行して実行し、両方のジョブチェーンの処理が終了したときにコールバックを実行するとしましょう。You may define a set of chained jobs[#job-chaining] within a batch by placing the chained jobs within an array. For example, we may execute two job chains in parallel and execute a callback when both job chains have finished processing:

use App\Jobs\ReleasePodcast;
use App\Jobs\SendPodcastReleaseNotification;
use Illuminate\Bus\Batch;
use Illuminate\Support\Facades\Bus;

Bus::batch([
    [
        new ReleasePodcast(1),
        new SendPodcastReleaseNotification(1),
    ],
    [
        new ReleasePodcast(2),
        new SendPodcastReleaseNotification(2),
    ],
])->then(function (Batch $batch) {
    // ...
})->dispatch();

逆に、チェーン内でバッチを定義すれば、チェーン内でジョブのバッチを実行できます。例えば、最初に複数のポッドキャストをリリースするジョブのバッチを実行し、次にリリース通知を送信するジョブのバッチを実行することができます:Conversely, you may run batches of jobs within a chain[#job-chaining] by defining batches within the chain. For example, you could first run a batch of jobs to release multiple podcasts then a batch of jobs to send the release notifications:

use App\Jobs\FlushPodcastCache;
use App\Jobs\ReleasePodcast;
use App\Jobs\SendPodcastReleaseNotification;
use Illuminate\Support\Facades\Bus;

Bus::chain([
    new FlushPodcastCache,
    Bus::batch([
        new ReleasePodcast(1),
        new ReleasePodcast(2),
    ]),
    Bus::batch([
        new SendPodcastReleaseNotification(1),
        new SendPodcastReleaseNotification(2),
    ]),
])->dispatch();

バッチへのジョブ追加Adding Jobs to Batches

バッチ処理するジョブ内からそのバッチへジョブを追加できると便利です。このパターンは、Webリクエスト中にディスパッチするのに時間がかかりすぎるだろう何千ものジョブをバッチ処理する必要がある場合に役立ちます。したがって、代わりに、バッチをより多くのジョブとハイドレイトする「ローダー」ジョブを最初のバッチとしてディスパッチすることを推奨します。Sometimes it may be useful to add additional jobs to a batch from within a batched job. This pattern can be useful when you need to batch thousands of jobs which may take too long to dispatch during a web request. So, instead, you may wish to dispatch an initial batch of "loader" jobs that hydrate the batch with even more jobs:

$batch = Bus::batch([
    new LoadImportBatch,
    new LoadImportBatch,
    new LoadImportBatch,
])->then(function (Batch $batch) {
    // すべてのジョブが正常に完了
})->name('Import Contacts')->dispatch();

この例では、LoadImportBatchジョブを使用して、追加のジョブでバッチをハイドレイトします。これを実現するために、ジョブのbatchメソッドを介してアクセスできるバッチインスタンスでaddメソッドを使用できます。In this example, we will use the LoadImportBatch job to hydrate the batch with additional jobs. To accomplish this, we may use the add method on the batch instance that may be accessed via the job's batch method:

use App\Jobs\ImportContacts;
use Illuminate\Support\Collection;

/**
 * ジョブの実行
 */
public function handle(): void
{
    if ($this->batch()->cancelled()) {
        return;
    }

    $this->batch()->add(Collection::times(1000, function () {
        return new ImportContacts;
    }));
}

warning Warning! 同じバッチに属するジョブ内からのみ、バッチにジョブを追加できます。[!WARNING]
You may only add jobs to a batch from within a job that belongs to the same batch.

バッチの検査Inspecting Batches

バッチ完了コールバックに渡されるIlluminate\Bus\Batchインスタンスは、特定のジョブのバッチを操作および検査をサポートするために、さまざまなプロパティとメソッドを用意しています。The Illuminate\Bus\Batch instance that is provided to batch completion callbacks has a variety of properties and methods to assist you in interacting with and inspecting a given batch of jobs:

// バッチのUUID
$batch->id;

// バッチの名前(該当する場合)
$batch->name;

// バッチに割り当てたジョブの数
$batch->totalJobs;

// キューにより処理されていないジョブの数
$batch->pendingJobs;

// 失敗したジョブの数
$batch->failedJobs;

// これまでに処理したジョブの数
$batch->processedJobs();

// バッチの完了率(0-100)
$batch->progress();

// バッチの実行が終了したかを判定
$batch->finished();

// バッチの実行をキャンセル
$batch->cancel();

// バッチがキャンセルされたかを判定
$batch->cancelled();

ルートからバッチを返すReturning Batches From Routes

すべてのIlluminate\Bus\BatchインスタンスはJSONシリアル化可能です。つまり、アプリケーションのルートの1つから直接それらを返し、完了の進行状況など、バッチに関する情報を含むJSONペイロードを取得できます。これにより、バッチの完了の進行状況に関する情報をアプリケーションのUIに表示するのに便利です。All Illuminate\Bus\Batch instances are JSON serializable, meaning you can return them directly from one of your application's routes to retrieve a JSON payload containing information about the batch, including its completion progress. This makes it convenient to display information about the batch's completion progress in your application's UI.

IDでバッチを取得するには、BusファサードのfindBatchメソッドを使用します。To retrieve a batch by its ID, you may use the Bus facade's findBatch method:

use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Route;

Route::get('/batch/{batchId}', function (string $batchId) {
    return Bus::findBatch($batchId);
});

バッチのキャンセルCancelling Batches

特定のバッチの実行をキャンセルする必要が起きることもあるでしょう。これは、Illuminate\Bus\Batchインスタンスでcancelメソッドを呼び出すことで実行できます。Sometimes you may need to cancel a given batch's execution. This can be accomplished by calling the cancel method on the Illuminate\Bus\Batch instance:

/**
 * ジョブの実行
 */
public function handle(): void
{
    if ($this->user->exceedsImportLimit()) {
        return $this->batch()->cancel();
    }

    if ($this->batch()->cancelled()) {
        return;
    }
}

前例で気づかれたかもしれませんが、バッチジョブは通常、実行を続ける前に対応するバッチがキャンセルされていることを判定する必要があります。しかし、便利なように、代わりに SkipIfBatchCancelled ミドルウェアをジョブへ割り当てできます。名前が示すように、このミドルウェアは、対応するバッチがキャンセルされた場合、ジョブを処理しないようにLaravelに指示します。As you may have noticed in the previous examples, batched jobs should typically determine if their corresponding batch has been cancelled before continuing execution. However, for convenience, you may assign the SkipIfBatchCancelled middleware[#job-middleware] to the job instead. As its name indicates, this middleware will instruct Laravel to not process the job if its corresponding batch has been cancelled:

use Illuminate\Queue\Middleware\SkipIfBatchCancelled;

/**
 * このジョブを通過させるミドルウェアを取得
 */
public function middleware(): array
{
    return [new SkipIfBatchCancelled];
}

バッチの失敗Batch Failures

バッチ処理されたジョブが失敗すると、catchコールバック(割り当てられている場合)が呼び出されます。このコールバックは、バッチ内で失敗した最初のジョブに対してのみ呼び出されます。When a batched job fails, the catch callback (if assigned) will be invoked. This callback is only invoked for the first job that fails within the batch.

失敗の許可Allowing Failures

バッチ内のジョブが失敗すると、Laravelは自動的にバッチを「キャンセル済み」としてマークします。必要に応じて、この動作を無効にして、ジョブの失敗によってバッチがキャンセル済みとして自動的にマークされないようにすることができます。これは、バッチのディスパッチ中にallowFailuresメソッドを呼び出すことで実現できます。When a job within a batch fails, Laravel will automatically mark the batch as "cancelled". If you wish, you may disable this behavior so that a job failure does not automatically mark the batch as cancelled. This may be accomplished by calling the allowFailures method while dispatching the batch:

$batch = Bus::batch([
    // ...
])->then(function (Batch $batch) {
    // すべてのジョブが正常に完了
})->allowFailures()->dispatch();

失敗したバッチジョブの再試行Retrying Failed Batch Jobs

便利なように、Laravelはqueue:retry-batch Artisanコマンドを用意しており、特定のバッチで失敗したすべてのジョブを簡単に再試行できます。queue:retry-batchコマンドは、失敗したジョブを再試行する必要があるバッチのUUIDを引数に取ります。For convenience, Laravel provides a queue:retry-batch Artisan command that allows you to easily retry all of the failed jobs for a given batch. The queue:retry-batch command accepts the UUID of the batch whose failed jobs should be retried:

php artisan queue:retry-batch 32dbc76c-4f82-4749-b610-a639fe0099b5

バッチの整理Pruning Batches

整理しないと、job_batchesテーブルにレコードがあっという間に蓄積されます。これを軽減するには、queue:prune-batches Artisanコマンドを毎日実行するようにスケジュールする必要があります。Without pruning, the job_batches table can accumulate records very quickly. To mitigate this, you should schedule[/docs/{{version}}/scheduling] the queue:prune-batches Artisan command to run daily:

use Illuminate\Support\Facades\Schedule;

Schedule::command('queue:prune-batches')->daily();

デフォルトでは、完了してから24時間以上経過したすべてのバッチが整理されます。バッチデータを保持する時間を決定するためにコマンド呼び出し時にhoursオプションを使用できます。たとえば、次のコマンドは48時間以上前に終了したすべてのバッチを削除します。By default, all finished batches that are more than 24 hours old will be pruned. You may use the hours option when calling the command to determine how long to retain batch data. For example, the following command will delete all batches that finished over 48 hours ago:

use Illuminate\Support\Facades\Schedule;

Schedule::command('queue:prune-batches --hours=48')->daily();

時々、jobs_batches テーブルに、ジョブが失敗して再試行も成功しなかったバッチなど、正常に完了しなかったバッチのバッチレコードが蓄積されることがあります。queue:prune-batchesコマンドでunfinishedオプションを使って、こうした未完了のバッチレコードを削除するように指示できます。Sometimes, your jobs_batches table may accumulate batch records for batches that never completed successfully, such as batches where a job failed and that job was never retried successfully. You may instruct the queue:prune-batches command to prune these unfinished batch records using the unfinished option:

use Illuminate\Support\Facades\Schedule;

Schedule::command('queue:prune-batches --hours=48 --unfinished=72')->daily();

jobs_batchesテーブルと同様に、キャンセルされたバッチレコードが蓄積されるかもしれません。queue:prune-batchesコマンドのcancelledオプションを使って、これらのキャンセルされたバッチレコードを整理ように指示してください。Likewise, your jobs_batches table may also accumulate batch records for cancelled batches. You may instruct the queue:prune-batches command to prune these cancelled batch records using the cancelled option:

use Illuminate\Support\Facades\Schedule;

Schedule::command('queue:prune-batches --hours=48 --cancelled=72')->daily();

DynamoDBへのバッチ保存Storing Batches in DynamoDB

Laravelでは、バッチのメタ情報をリレーショナルデータベースではなく、DynamoDBへ格納する方法もサポートしています。ただし、バッチレコードをすべて格納する、DynamoDBテーブルを手作業で作成する必要があります。Laravel also provides support for storing batch meta information in DynamoDB[https://aws.amazon.com/dynamodb] instead of a relational database. However, you will need to manually create a DynamoDB table to store all of the batch records.

通常、このテーブルはjob_batchesという名前にしますが、アプリケーションのqueue設定ファイル内のqueue.batching.table設定値に基づいて名前を付ける必要があります。Typically, this table should be named job_batches, but you should name the table based on the value of the queue.batching.table configuration value within your application's queue configuration file.

DynamoDBバッチテーブル設定DynamoDB Batch Table Configuration

job_batchesテーブルには、applicationという文字列のプライマリパーティションキーとidという文字列のプライマリソートキーを設定してください。キーのapplicationの部分には、アプリケーションのapp設定ファイル内のname設定値で定義したアプリケーション名が格納されます。アプリケーション名はDynamoDBテーブルのキーの一部なので、同じテーブルを使って複数のLaravelアプリケーションのジョブバッチを格納できます。The job_batches table should have a string primary partition key named application and a string primary sort key named id. The application portion of the key will contain your application's name as defined by the name configuration value within your application's app configuration file. Since the application name is part of the DynamoDB table's key, you can use the same table to store job batches for multiple Laravel applications.

さらに、自動バッチ整理を利用したい場合は、テーブルにttl属性を定義することもできます。In addition, you may define ttl attribute for your table if you would like to take advantage of automatic batch pruning[#pruning-batches-in-dynamodb].

DynamoDB設定DynamoDB Configuration

次に、LaravelアプリケーションがAmazon DynamoDBと通信できるように、AWS SDKをインストールします。Next, install the AWS SDK so that your Laravel application can communicate with Amazon DynamoDB:

composer require aws/aws-sdk-php

次に、queue.batching.driver設定オプションの値をdynamodbに設定します。さらに、batching設定配列内で、keysecretregion設定オプションを定義してください。これらのオプションはAWSとの認証に使用します。dynamodbドライバを使用する場合、queue.batching.database設定オプションは不要です。Then, set the queue.batching.driver configuration option's value to dynamodb. In addition, you should define key, secret, and region configuration options within the batching configuration array. These options will be used to authenticate with AWS. When using the dynamodb driver, the queue.batching.database configuration option is unnecessary:

'batching' => [
    'driver' => env('QUEUE_BATCHING_DRIVER', 'dynamodb'),
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
    'table' => 'job_batches',
],

DynamoDBでのバッチの整理Pruning Batches in DynamoDB

DynamoDBを使用してジョブバッチ情報を保存する場合、リレーショナルデータベースへ保存したバッチを削除する、一般的なコマンドは機能しません。代わりに、DynamoDBのネイティブTTL機能を利用して、古いバッチのレコードを自動的に削除できます。When utilizing DynamoDB[https://aws.amazon.com/dynamodb] to store job batch information, the typical pruning commands used to prune batches stored in a relational database will not work. Instead, you may utilize DynamoDB's native TTL functionality[https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html] to automatically remove records for old batches.

DynamoDBのテーブルにttl属性を定義した場合、Laravelにバッチレコードの整理方法を指示する設定パラメータを定義できます。queue.batching.ttl_attribute設定値はTTLを保持する属性名を定義し、queue.batching.ttl設定値は、最後に更新されてからバッチレコードがDynamoDBテーブルから削除されるまでの秒数を定義します。If you defined your DynamoDB table with a ttl attribute, you may define configuration parameters to instruct Laravel how to prune batch records. The queue.batching.ttl_attribute configuration value defines the name of the attribute holding the TTL, while the queue.batching.ttl configuration value defines the number of seconds after which a batch record can be removed from the DynamoDB table, relative to the last time the record was updated:

'batching' => [
    'driver' => env('QUEUE_FAILED_DRIVER', 'dynamodb'),
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
    'table' => 'job_batches',
    'ttl_attribute' => 'ttl',
    'ttl' => 60 * 60 * 24 * 7, // 7日
],

クロージャのキュー投入Queueing Closures

ジョブクラスをキューにディスパッチする代わりに、クロージャをディスパッチすることもできます。これは、現在のリクエストサイクルの外で実行する必要がある迅速で単純なタスクに最適です。クロージャをキューにディスパッチする場合、クロージャのコードコンテンツは暗号で署名されているため、転送中に変更することはできません。Instead of dispatching a job class to the queue, you may also dispatch a closure. This is great for quick, simple tasks that need to be executed outside of the current request cycle. When dispatching closures to the queue, the closure's code content is cryptographically signed so that it cannot be modified in transit:

$podcast = App\Podcast::find(1);

dispatch(function () use ($podcast) {
    $podcast->publish();
});

catchメソッドを使用して、キューで設定した再試行をすべて使い果たしても、キュー投入したクロージャが正常に完了しなかった場合に実行する必要があるクロージャを提供できます。Using the catch method, you may provide a closure that should be executed if the queued closure fails to complete successfully after exhausting all of your queue's configured retry attempts[#max-job-attempts-and-timeout]:

use Throwable;

dispatch(function () use ($podcast) {
    $podcast->publish();
})->catch(function (Throwable $e) {
    // このジョブは失敗
});

warning Warning! catchコールバックはシリアライズされ、Laravel のキューにより後ほど実行されるため、catchコールバック内で$this変数を使用するべきではありません。[!WARNING]
Since catch callbacks are serialized and executed at a later time by the Laravel queue, you should not use the $this variable within catch callbacks.

キューワーカの実行Running the Queue Worker

queue:workコマンドThe queue:work Command

Laravelは、キューワーカを開始し、キューに投入された新しいジョブを処理するArtisanコマンドを用意しています。queue:work Artisanコマンドを使用してワーカを実行します。queue:workコマンドを開始すると、手作業で停止するか、ターミナルを閉じるまで実行され続けることに注意してください。Laravel includes an Artisan command that will start a queue worker and process new jobs as they are pushed onto the queue. You may run the worker using the queue:work Artisan command. Note that once the queue:work command has started, it will continue to run until it is manually stopped or you close your terminal:

php artisan queue:work

lightbulb Note: queue:workプロセスをバックグラウンドで永続的に実行し続けるには、Supervisorなどのプロセスモニタを使用して、キューワーカの実行が停止しないようにする必要があります。[!NOTE]
To keep the queue:work process running permanently in the background, you should use a process monitor such as Supervisor[#supervisor-configuration] to ensure that the queue worker does not stop running.

処理済みのジョブIDをコマンド出力へ含めたい場合は、queue:workコマンドを実行する際に、-vフラグを指定します。You may include the -v flag when invoking the queue:work command if you would like the processed job IDs to be included in the command's output:

php artisan queue:work -v

キューワーカは長期間有効なプロセスであり、起動した時点のアプリケーションの状態をメモリに保存することを忘れないでください。その結果、起動後にコードベースの変更に気付くことはありません。したがって、デプロイメントプロセス中で、必ずキューワーカを再起動してください。さらに、アプリケーションによって作成または変更された静的状態は、ジョブ間で自動的にリセットされないことに注意してください。Remember, queue workers are long-lived processes and store the booted application state in memory. As a result, they will not notice changes in your code base after they have been started. So, during your deployment process, be sure to restart your queue workers[#queue-workers-and-deployment]. In addition, remember that any static state created or modified by your application will not be automatically reset between jobs.

もしくは、queue:listenコマンドを実行することもできます。queue:listenコマンドを使用する場合、更新されたコードをリロードしたり、アプリケーションの状態をリセットしたりするときに、ワーカを手作業で再起動する必要はありません。ただし、このコマンドはqueue:workコマンドよりも大幅に効率が低くなります。Alternatively, you may run the queue:listen command. When using the queue:listen command, you don't have to manually restart the worker when you want to reload your updated code or reset the application state; however, this command is significantly less efficient than the queue:work command:

php artisan queue:listen

複数のキューワーカの実行Running Multiple Queue Workers

複数のワーカをキューへ割り当ててジョブを同時に処理するには、複数のqueue:workプロセスを開始するだけです。これは、ターミナルの複数のタブを介してローカルで実行することも、プロセスマネージャの設定設定を使用して本番環境で実行することもできます。スーパーバイザーを使用する場合numprocs設定値が使用できます。To assign multiple workers to a queue and process jobs concurrently, you should simply start multiple queue:work processes. This can either be done locally via multiple tabs in your terminal or in production using your process manager's configuration settings. When using Supervisor[#supervisor-configuration], you may use the numprocs configuration value.

接続とキューの指定Specifying the Connection and Queue

ワーカが使用するキュー接続を指定することもできます。workコマンドに渡される接続名は、config/queue.php設定ファイルで定義されている接続の1つに対応している必要があります。You may also specify which queue connection the worker should utilize. The connection name passed to the work command should correspond to one of the connections defined in your config/queue.php configuration file:

php artisan queue:work redis

デフォルトでqueue:workコマンドは、指定された接続のデフォルトキューのジョブのみを処理します。しかしながら、指定する接続で特定のキューのみを処理することで、キューワーカをさらにカスタマイズできます。たとえば、すべてのメールをredisキュー接続のemailsキューで処理する場合、次のコマンドを発行して、そのキューのみを処理するワーカを起動できます。By default, the queue:work command only processes jobs for the default queue on a given connection. However, you may customize your queue worker even further by only processing particular queues for a given connection. For example, if all of your emails are processed in an emails queue on your redis queue connection, you may issue the following command to start a worker that only processes that queue:

php artisan queue:work redis --queue=emails

指定数ジョブの処理Processing a Specified Number of Jobs

--onceオプションを使用して、キューから1つのジョブのみを処理するようにワーカに指示できます。The --once option may be used to instruct the worker to only process a single job from the queue:

php artisan queue:work --once

--max-jobsオプションを使用して、指定する数のジョブを処理してから終了するようにワーカに指示できます。このオプションは、Supervisorと組み合わせると便利な場合があります。これにより、ワーカは、指定する数のジョブを処理した後に自動的に再起動され、蓄積された可能性のあるメモリが解放されます。The --max-jobs option may be used to instruct the worker to process the given number of jobs and then exit. This option may be useful when combined with Supervisor[#supervisor-configuration] so that your workers are automatically restarted after processing a given number of jobs, releasing any memory they may have accumulated:

php artisan queue:work --max-jobs=1000

キュー投入したすべてのジョブを処理後に終了Processing All Queued Jobs and Then Exiting

--stop-when-emptyオプションを使用して、すべてのジョブを処理してから正常に終了するようにワーカに指示できます。このオプションは、Dockerコンテナ内のLaravelキューを処理するときに、キューが空になった後にコンテナをシャットダウンする場合に役立ちます。The --stop-when-empty option may be used to instruct the worker to process all jobs and then exit gracefully. This option can be useful when processing Laravel queues within a Docker container if you wish to shutdown the container after the queue is empty:

php artisan queue:work --stop-when-empty

Processing Jobs for a Given Number of SecondsProcessing Jobs for a Given Number of Seconds

--max-timeオプションを使用して、指定する秒数の間ジョブを処理してから終了するようにワーカに指示できます。このオプションは、Supervisorと組み合わせると便利な場合があります。これにより、ジョブを一定時間処理した後、ワーカが自動的に再起動され、蓄積された可能性のあるメモリが解放されます。The --max-time option may be used to instruct the worker to process jobs for the given number of seconds and then exit. This option may be useful when combined with Supervisor[#supervisor-configuration] so that your workers are automatically restarted after processing jobs for a given amount of time, releasing any memory they may have accumulated:

# Process jobs for one hour and then exit...
php artisan queue:work --max-time=3600

ワーカのスリープ期間Worker Sleep Duration

キューにジョブが現れると、ワーカはジョブの処理を遅延なく処理し続けます。しかし、sleepオプションを指定する場合、利用可能なジョブがない場合、ワーカは指定秒数間「スリープ」します。もちろん、スリープ中はワーカは新しいジョブを処理しません。When jobs are available on the queue, the worker will keep processing jobs with no delay in between jobs. However, the sleep option determines how many seconds the worker will "sleep" if there are no jobs available. Of course, while sleeping, the worker will not process any new jobs:

php artisan queue:work --sleep=3

メンテナンスモードとキューMaintenance Mode and Queues

アプリケーションがメンテナンスモードの間は、キューへ投入したジョブを処理しません。アプリケーションのメンテナンスモードが解除されると、通常通りジョブを処理します。While your application is in maintenance mode[/docs/{{version}}/configuration#maintenance-mode], no queued jobs will be handled. The jobs will continue to be handled as normal once the application is out of maintenance mode.

メンテナンスモードが有効になっていても、キューワーカにジョブを処理させるには、--forceオプションを使用します:To force your queue workers to process jobs even if maintenance mode is enabled, you may use --force option:

php artisan queue:work --force

リソースに関する検討事項Resource Considerations

デーモンキューワーカは、各ジョブを処理する前にフレームワークを「再起動」しません。したがって、各ジョブが完了した後、重いリソースを解放する必要があります。たとえば、GDライブラリを使用して画像操作を行っている場合は、画像の処理が完了したら、imagedestroyを使用してメモリを解放する必要があります。Daemon queue workers do not "reboot" the framework before processing each job. Therefore, you should release any heavy resources after each job completes. For example, if you are doing image manipulation with the GD library, you should free the memory with imagedestroy when you are done processing the image.

キューの優先度Queue Priorities

キューの処理方法に優先順位を付けたい場合があります。たとえば、config/queue.php設定ファイルで、デフォルトqueueredis接続のlowに設定できます。ただし、次のように、ジョブをhigh優先度キューに投入したい場合もあるでしょう。Sometimes you may wish to prioritize how your queues are processed. For example, in your config/queue.php configuration file, you may set the default queue for your redis connection to low. However, occasionally you may wish to push a job to a high priority queue like so:

dispatch((new Job)->onQueue('high'));

lowキューのジョブを続行する前に、すべてのhighキュージョブが処理されていることを確認するワーカを開始するには、キュー名のコンマ区切りリストをworkコマンドに渡します。To start a worker that verifies that all of the high queue jobs are processed before continuing to any jobs on the low queue, pass a comma-delimited list of queue names to the work command:

php artisan queue:work --queue=high,low

キューワーカと開発Queue Workers and Deployment

キューワーカは存続期間の長いプロセスであるため、再起動しない限り、コードの変更が反映されることはありません。したがって、キューワーカを使用してアプリケーションをデプロイする最も簡単な方法は、デプロイメントプロセス中にワーカを再起動することです。queue:restartコマンドを発行することにより、すべてのワーカを正常に再起動できます。Since queue workers are long-lived processes, they will not notice changes to your code without being restarted. So, the simplest way to deploy an application using queue workers is to restart the workers during your deployment process. You may gracefully restart all of the workers by issuing the queue:restart command:

php artisan queue:restart

このコマンドは、既存のジョブが失われないように、現在のジョブの処理が終了した後、すべてのキューワーカに正常に終了するように指示します。queue:restartコマンドを実行するとキューワーカが終了するため、Supervisorなどのプロセスマネージャを実行して、キューワーカを自動的に再起動する必要があります。This command will instruct all queue workers to gracefully exit after they finish processing their current job so that no existing jobs are lost. Since the queue workers will exit when the queue:restart command is executed, you should be running a process manager such as Supervisor[#supervisor-configuration] to automatically restart the queue workers.

lightbulb Note: キューはキャッシュを使用して再起動シグナルを保存するため、この機能を使用する前に、アプリケーションに対してキャッシュドライバが適切に設定されていることを確認する必要があります。[!NOTE]
The queue uses the cache[/docs/{{version}}/cache] to store restart signals, so you should verify that a cache driver is properly configured for your application before using this feature.

ジョブの有効期限とタイムアウトJob Expirations and Timeouts

ジョブの有効期限Job Expiration

config/queue.php設定ファイルで、各キュー接続ごとにretry_afterオプションが定義されています。このオプションは、処理中のジョブを再試行する前にキュー接続が待機する秒数を指定します。たとえば、retry_afterの値が90に設定されている場合、ジョブが解放または削除されずに90秒間処理されていれば、ジョブはキューに解放されます。通常、retry_after値は、ジョブが処理を完了するのに合理的にかかる最大秒数に設定する必要があります。In your config/queue.php configuration file, each queue connection defines a retry_after option. This option specifies how many seconds the queue connection should wait before retrying a job that is being processed. For example, if the value of retry_after is set to 90, the job will be released back onto the queue if it has been processing for 90 seconds without being released or deleted. Typically, you should set the retry_after value to the maximum number of seconds your jobs should reasonably take to complete processing.

warning Warning! retry_after値を含まない唯一のキュー接続はAmazon SQSです。SQSは、AWSコンソール内で管理しているDefault Visibility Timeoutに基づいてジョブを再試行します。[!WARNING]
The only queue connection which does not contain a retry_after value is Amazon SQS. SQS will retry the job based on the Default Visibility Timeout[https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/AboutVT.html] which is managed within the AWS console.

ワーカタイムアウトWorker Timeouts

queue:work Artisanコマンドは--timeoutオプションを用意しています。--timeoutのデフォルト値は60秒です。ジョブがタイムアウト値で指定する秒数より長く処理されている場合、ジョブを処理しているワーカはエラーで終了します。通常、ワーカはサーバで構築済みのプロセスマネージャによって自動的に再起動されます。The queue:work Artisan command exposes a --timeout option. By default, the --timeout value is 60 seconds. If a job is processing for longer than the number of seconds specified by the timeout value, the worker processing the job will exit with an error. Typically, the worker will be restarted automatically by a process manager configured on your server[#supervisor-configuration]:

php artisan queue:work --timeout=60

retry_after設定オプションと--timeout CLIオプションは異なりますが、ジョブが失われないように、またジョブが1回だけ正常に処理されるように連携して機能します。The retry_after configuration option and the --timeout CLI option are different, but work together to ensure that jobs are not lost and that jobs are only successfully processed once.

warning Warning! --timeout値は、常にretry_after設定値より少なくとも数秒短くする必要があります。これにより、フリーズしたジョブを処理しているワーカは、ジョブが再試行される前に常に終了します。--timeoutオプションがretry_after設定値よりも長い場合、ジョブは2回処理される可能性があります。[!WARNING]
The --timeout value should always be at least several seconds shorter than your retry_after configuration value. This will ensure that a worker processing a frozen job is always terminated before the job is retried. If your --timeout option is longer than your retry_after configuration value, your jobs may be processed twice.

Supervisor設定Supervisor Configuration

本番環境では、queue:workプロセスを実行し続ける手段が必要です。queue:workプロセスは、ワーカタイムアウトの超過や、queue:restartコマンドの実行など、さまざまな理由で実行を停止する場合があります。In production, you need a way to keep your queue:work processes running. A queue:work process may stop running for a variety of reasons, such as an exceeded worker timeout or the execution of the queue:restart command.

このため、queue:workプロセスが終了したことを検出し、自動的に再起動できるプロセスモニタを構築する必要があります。さらに、プロセスモニタを使用すると、同時に実行するqueue:workプロセスの数を指定できます。Supervisorは、Linux環境で一般的に使用されるプロセスモニタであり、以下のドキュメントでその設定方法について説明します。For this reason, you need to configure a process monitor that can detect when your queue:work processes exit and automatically restart them. In addition, process monitors can allow you to specify how many queue:work processes you would like to run concurrently. Supervisor is a process monitor commonly used in Linux environments and we will discuss how to configure it in the following documentation.

SupervisorのインストールInstalling Supervisor

SupervisorはLinuxオペレーティングシステムのプロセスモニターであり、落ちた場合にqueue:workプロセスを自動的に再起動します。UbuntuにSupervisorをインストールするには、次のコマンドを使用します。Supervisor is a process monitor for the Linux operating system, and will automatically restart your queue:work processes if they fail. To install Supervisor on Ubuntu, you may use the following command:

sudo apt-get install supervisor

lightbulb Note: 自分でSupervisorを設定および管理するのが難しいと思われる場合は、Laravel Forgeの使用を検討してください。これにより、本番LaravelプロジェクトのSupervisorが自動的にインストールおよび設定されます。[!NOTE]
If configuring and managing Supervisor yourself sounds overwhelming, consider using Laravel Forge[https://forge.laravel.com], which will automatically install and configure Supervisor for your production Laravel projects.

Supervisorの設定Configuring Supervisor

Supervisor設定ファイルは通常、/etc/supervisor/conf.dディレクトリに保管されます。このディレクトリ内に、プロセスの監視方法をSupervisorに指示する設定ファイルをいくつでも作成できます。たとえば、queue:workプロセスを開始および監視するlaravel-worker.confファイルを作成してみましょう。Supervisor configuration files are typically stored in the /etc/supervisor/conf.d directory. Within this directory, you may create any number of configuration files that instruct supervisor how your processes should be monitored. For example, let's create a laravel-worker.conf file that starts and monitors queue:work processes:

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/forge/app.com/artisan queue:work sqs --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=forge
numprocs=8
redirect_stderr=true
stdout_logfile=/home/forge/app.com/worker.log
stopwaitsecs=3600

この例中のnumprocsディレクティブは、スーパーバイザーへ8つのqueue:workプロセスを実行し、それらすべてを監視し、失敗した場合は自動的に再起動するように指示します。必要なキュー接続とワーカオプションを反映するように、設定のcommandディレクティブを変更する必要があります。In this example, the numprocs directive will instruct Supervisor to run eight queue:work processes and monitor all of them, automatically restarting them if they fail. You should change the command directive of the configuration to reflect your desired queue connection and worker options.

warning Warning! stopwaitsecsの値が、最も長く実行されるジョブが消費する秒数よりも大きいことを確認する必要があります。そうしないと、Supervisorは処理が完了する前にジョブを強制終了する可能性があります。[!WARNING]
You should ensure that the value of stopwaitsecs is greater than the number of seconds consumed by your longest running job. Otherwise, Supervisor may kill the job before it is finished processing.

Supervisorの起動Starting Supervisor

設定ファイルを作成したら、以下のコマンドを使用して、Supervisor設定を更新し、プロセスを開始できます。Once the configuration file has been created, you may update the Supervisor configuration and start the processes using the following commands:

sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl start "laravel-worker:*"

Supervisorの詳細は、Supervisorのドキュメントを参照してください。For more information on Supervisor, consult the Supervisor documentation[http://supervisord.org/index.html].

失敗したジョブの処理Dealing With Failed Jobs

キュー投入したジョブは、失敗することがあります。心配いりません。物事は常に計画通りに進むわけではありません。Laravelには、ジョブを試行する最大回数を指定する便利な方法があります。非同期ジョブがこの試行回数を超えると、そのジョブはfailed_jobsデータベーステーブルに挿入されます。同期的にディスパッチするジョブは失敗してもこのテーブルへ格納せず、その例外は直ちにアプリケーションにより処理されます。Sometimes your queued jobs will fail. Don't worry, things don't always go as planned! Laravel includes a convenient way to specify the maximum number of times a job should be attempted[#max-job-attempts-and-timeout]. After an asynchronous job has exceeded this number of attempts, it will be inserted into the failed_jobs database table. Synchronously dispatched jobs[/docs/{{version}}/queues#synchronous-dispatching] that fail are not stored in this table and their exceptions are immediately handled by the application.

failed_jobsテーブルを作成するマイグレーションは、通常、新しいLaravelアプリケーションにはあらかじめ存在しています。しかし、アプリケーションにこのテーブルのマイグレーションが含まれていない場合は、make:queue-failed-tableコマンドを使い作成できます。A migration to create the failed_jobs table is typically already present in new Laravel applications. However, if your application does not contain a migration for this table, you may use the make:queue-failed-table command to create the migration:

php artisan make:queue-failed-table

php artisan migrate

キューワーカプロセスを実行する場合、queue:workコマンドの--triesスイッチを使用してジョブを試行する最大回数を指定できます。--triesオプションの値を指定しない場合、ジョブは1回だけ、またはジョブクラスの$triesプロパティで指定する回数だけ試行されます。When running a queue worker[#running-the-queue-worker] process, you may specify the maximum number of times a job should be attempted using the --tries switch on the queue:work command. If you do not specify a value for the --tries option, jobs will only be attempted once or as many times as specified by the job class' $tries property:

php artisan queue:work redis --tries=3

--backoffオプションを使用して、例外が発生したジョブを再試行する前にLaravelが待機する秒数を指定できます。デフォルトでは、ジョブはすぐにキューに戻され、再試行されます。Using the --backoff option, you may specify how many seconds Laravel should wait before retrying a job that has encountered an exception. By default, a job is immediately released back onto the queue so that it may be attempted again:

php artisan queue:work redis --tries=3 --backoff=3

例外が発生したジョブを再試行する前にLaravelが待機する秒数をジョブごとに設定したい場合は、ジョブクラスにbackoffプロパティを定義することで設定できます。If you would like to configure how many seconds Laravel should wait before retrying a job that has encountered an exception on a per-job basis, you may do so by defining a backoff property on your job class:

/**
 * ジョブを再試行する前に待機する秒数
 *
 * @var int
 */
public $backoff = 3;

ジョブのバックオフ時間を決定するために複雑なロジックが必要な場合は、ジョブクラスでbackoffメソッドを定義します。If you require more complex logic for determining the job's backoff time, you may define a backoff method on your job class:

/**
* ジョブを再試行する前に待機する秒数を計算
*/
public function backoff(): int
{
    return 3;
}

backoffメソッドからバックオフ値の配列を返すことで、「指数」バックオフを簡単に設定できます。この例では、再試行の遅延は最初の最初の再試行で1秒、2回目の再試行で5秒、3回目の再試行で10秒、それ以降も再試行が残っている場合は毎回10秒となります:You may easily configure "exponential" backoffs by returning an array of backoff values from the backoff method. In this example, the retry delay will be 1 second for the first retry, 5 seconds for the second retry, 10 seconds for the third retry, and 10 seconds for every subsequent retry if there are more attempts remaining:

/**
* ジョブを再試行する前に待機する秒数を計算
*
* @return array<int, int>
*/
public function backoff(): array
{
    return [1, 5, 10];
}

ジョブ失敗後の片付けCleaning Up After Failed Jobs

特定のジョブが失敗した場合、ユーザーにアラートを送信するか、ジョブによって部分的に完了したアクションを元に戻すことができます。これを実現するために、ジョブクラスでfailedメソッドを定義できます。ジョブの失敗の原因となったThrowableインスタンスは、failedメソッドへ渡されます。When a particular job fails, you may want to send an alert to your users or revert any actions that were partially completed by the job. To accomplish this, you may define a failed method on your job class. The Throwable instance that caused the job to fail will be passed to the failed method:

<?php

namespace App\Jobs;

use App\Models\Podcast;
use App\Services\AudioProcessor;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Throwable;

class ProcessPodcast implements ShouldQueue
{
    use Queueable;

    /**
     * 新しいジョブインスタンスの生成
     */
    public function __construct(
        public Podcast $podcast,
    ) {}

    /**
     * ジョブの実行
     */
    public function handle(AudioProcessor $processor): void
    {
        // アップロードされたポッドキャストを処理…
    }

    /**
     * ジョブの失敗を処理
     */
    public function failed(?Throwable $exception): void
    {
        // ユーザーへ失敗を通知するなど…
    }
}

warning Warning! failedメソッドを呼び出す前に、ジョブが新しくインスタンス化されます。したがって、handleメソッド内で発生した可能性があるクラスプロパティの変更は失われます。[!WARNING]
A new instance of the job is instantiated before invoking the failed method; therefore, any class property modifications that may have occurred within the handle method will be lost.

失敗したジョブの再試行Retrying Failed Jobs

failed_jobsデータベーステーブルに挿入されたすべての失敗したジョブを表示するには、queue:failed Artisanコマンドを使用します。To view all of the failed jobs that have been inserted into your failed_jobs database table, you may use the queue:failed Artisan command:

php artisan queue:failed

queue:failedコマンドは、ジョブID、接続、キュー、失敗時間、およびジョブに関するその他の情報を一覧表示します。ジョブIDは、失敗したジョブを再試行するために使用できます。たとえば、IDがce7bb17c-cdd8-41f0-a8ec-7b4fef4e5eceの失敗したジョブを再試行するには、次のコマンドを発行します。The queue:failed command will list the job ID, connection, queue, failure time, and other information about the job. The job ID may be used to retry the failed job. For instance, to retry a failed job that has an ID of ce7bb17c-cdd8-41f0-a8ec-7b4fef4e5ece, issue the following command:

php artisan queue:retry ce7bb17c-cdd8-41f0-a8ec-7b4fef4e5ece

必要に応じ、複数のIDをコマンドへ渡せます。If necessary, you may pass multiple IDs to the command:

php artisan queue:retry ce7bb17c-cdd8-41f0-a8ec-7b4fef4e5ece 91401d2c-0784-4f43-824c-34f94a33c24d

指定するキューの失敗したジョブをすべて再試行することもできます。You may also retry all of the failed jobs for a particular queue:

php artisan queue:retry --queue=name

失敗したすべてのジョブを再試行するには、queue:retryコマンドを実行し、IDとしてallを渡します。To retry all of your failed jobs, execute the queue:retry command and pass all as the ID:

php artisan queue:retry all

失敗したジョブを削除したい場合は、queue:forgetコマンドを使用します。If you would like to delete a failed job, you may use the queue:forget command:

php artisan queue:forget 91401d2c-0784-4f43-824c-34f94a33c24d

lightbulb Note: Horizo​​nを使用する場合は、queue:forgetコマンドの代わりにhorizo​​n:forgetコマンドを使用して失敗したジョブを削除する必要があります。[!NOTE]
When using Horizon[/docs/{{version}}/horizon], you should use the horizon:forget command to delete a failed job instead of the queue:forget command.

失敗したすべてのジョブをfailed_jobsテーブルから削除するには、queue:flushコマンドを使用します。To delete all of your failed jobs from the failed_jobs table, you may use the queue:flush command:

php artisan queue:flush

見つからないモデルの無視Ignoring Missing Models

Eloquentモデルをジョブに挿入すると、モデルは自動的にシリアル化されてからキューに配置され、ジョブの処理時にデータベースから再取得されます。ただし、ジョブがワーカによる処理を待機している間にモデルが削除された場合、ジョブはModelNotFoundExceptionで失敗する可能性があります。When injecting an Eloquent model into a job, the model is automatically serialized before being placed on the queue and re-retrieved from the database when the job is processed. However, if the model has been deleted while the job was waiting to be processed by a worker, your job may fail with a ModelNotFoundException.

利便性のため、ジョブのdeleteWhenMissingModelsプロパティをtrueに設定することで、モデルが見つからないジョブを自動的に削除できます。このプロパティがtrueに設定されている場合、Laravelは例外を発生させることなく静かにジョブを破棄します。For convenience, you may choose to automatically delete jobs with missing models by setting your job's deleteWhenMissingModels property to true. When this property is set to true, Laravel will quietly discard the job without raising an exception:

/**
 * モデルが存在しなくなった場合は、ジョブを削除
 *
 * @var bool
 */
public $deleteWhenMissingModels = true;

失敗したジョブの切り詰めPruning Failed Jobs

アプリケーションのfailed_jobsテーブルのレコードを切り詰めるには、queue:prune-failed Artisanコマンドを実行します。You may prune the records in your application's failed_jobs table by invoking the queue:prune-failed Artisan command:

php artisan queue:prune-failed

デフォルトでは、24時間以上前の失敗したジョブの記録をすべて切り捨てます。コマンドに--hoursオプションを指定すると、直近のN時間以内に挿入された、失敗したジョブ記録のみを保持します。たとえば、次のコマンドは48時間以上前に挿入された、失敗したジョブのレコードをすべて削除します。By default, all the failed job records that are more than 24 hours old will be pruned. If you provide the --hours option to the command, only the failed job records that were inserted within the last N number of hours will be retained. For example, the following command will delete all the failed job records that were inserted more than 48 hours ago:

php artisan queue:prune-failed --hours=48

失敗したジョブのDynamoDBへの保存Storing Failed Jobs in DynamoDB

Laravelでは、失敗したジョブレコードをリレーショナルデータベースのテーブルではなく、DynamoDBへ保存するサポートも提供しています。ただし、失敗したジョブの記録をすべて保存するための、DynamoDBテーブルを手作業で作成しておく必要があります。通常、このテーブルはfailed_jobsという名前になりますが、アプリケーションのqueue設定ファイル内のqueue.failed.table設定値に基づいて、テーブル名を付ける必要があります。Laravel also provides support for storing your failed job records in DynamoDB[https://aws.amazon.com/dynamodb] instead of a relational database table. However, you must manually create a DynamoDB table to store all of the failed job records. Typically, this table should be named failed_jobs, but you should name the table based on the value of the queue.failed.table configuration value within your application's queue configuration file.

failed_jobsテーブルは、applicationという名前で文字列のプライマリパーティションキーと、uuidという名前の文字列のプライマリソートキーを持つ必要があります。キーのapplication部分には、アプリケーションのapp設定ファイル内のname設定値で定義したアプリケーション名が含まれます。アプリケーション名はDynamoDBテーブルのキーの一部なので、同じテーブルを使って複数のLaravelアプリケーションの失敗したジョブを保存できます。The failed_jobs table should have a string primary partition key named application and a string primary sort key named uuid. The application portion of the key will contain your application's name as defined by the name configuration value within your application's app configuration file. Since the application name is part of the DynamoDB table's key, you can use the same table to store failed jobs for multiple Laravel applications.

さらに、LaravelアプリケーションがAmazon DynamoDBと通信できるように、AWS SDKを確実にインストールしてください。In addition, ensure that you install the AWS SDK so that your Laravel application can communicate with Amazon DynamoDB:

composer require aws/aws-sdk-php

次に、queue.failed.driver設定オプションの値をdynamodbに設定します。さらに、失敗したジョブの設定配列の中で、keysecretregionの構成オプションを定義します。これらのオプションはAWSとの認証に使用されます。dynamodbドライバを使用する場合、queue.failed.database設定オプションは不要です。Next, set the queue.failed.driver configuration option's value to dynamodb. In addition, you should define key, secret, and region configuration options within the failed job configuration array. These options will be used to authenticate with AWS. When using the dynamodb driver, the queue.failed.database configuration option is unnecessary:

'failed' => [
    'driver' => env('QUEUE_FAILED_DRIVER', 'dynamodb'),
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
    'table' => 'failed_jobs',
],

失敗したジョブの保存の無効化Disabling Failed Job Storage

queue.failed.driver設定オプションの値をnullにすることで、失敗したジョブを保存せず、破棄するようにLaravelへ指示できます。通常、これはQUEUE_FAILED_DRIVER環境変数の設定で実現します。You may instruct Laravel to discard failed jobs without storing them by setting the queue.failed.driver configuration option's value to null. Typically, this may be accomplished via the QUEUE_FAILED_DRIVER environment variable:

QUEUE_FAILED_DRIVER=null

失敗したジョブイベントFailed Job Events

ジョブが失敗したときに呼び出されるイベントリスナを登録する場合は、Queueファサードのfailingメソッドを使用できます。たとえば、Laravelに含まれているAppServiceProviderbootメソッドからこのイベントにクロージャをアタッチできます。If you would like to register an event listener that will be invoked when a job fails, you may use the Queue facade's failing method. For example, we may attach a closure to this event from the boot method of the AppServiceProvider that is included with Laravel:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Queue;
use Illuminate\Support\ServiceProvider;
use Illuminate\Queue\Events\JobFailed;

class AppServiceProvider extends ServiceProvider
{
    /**
     * 全アプリケーションサービスの登録
     */
    public function register(): void
    {
        // ...
    }

    /**
     * 全アプリケーションサービスの初期起動処理
     */
    public function boot(): void
    {
        Queue::failing(function (JobFailed $event) {
            // $event->connectionName
            // $event->job
            // $event->exception
        });
    }
}

キューからのジョブクリアClearing Jobs From Queues

lightbulb Note: Horizo​​nを使用する場合は、queue:clearコマンドの代わりにhorizo​​n:clearコマンドを使用してキューからジョブをクリアする必要があります。[!NOTE]
When using Horizon[/docs/{{version}}/horizon], you should use the horizon:clear command to clear jobs from the queue instead of the queue:clear command.

デフォルト接続のデフォルトキューからすべてのジョブを削除する場合は、queue:clearArtisanコマンドを使用して削除します。If you would like to delete all jobs from the default queue of the default connection, you may do so using the queue:clear Artisan command:

php artisan queue:clear

特定の接続とキューからジョブを削除するために、connection引数とqueueオプションを指定することもできます。You may also provide the connection argument and queue option to delete jobs from a specific connection and queue:

php artisan queue:clear redis --queue=emails

warning Warning! キューからのジョブのクリアは、SQS、Redis、およびデータベースキュードライバでのみ使用できます。さらに、SQSメッセージの削除プロセスには最長60秒かかるため、キューをクリアしてから最長60秒後にSQSキューに送信されたジョブも削除される可能性があります。[!WARNING]
Clearing jobs from queues is only available for the SQS, Redis, and database queue drivers. In addition, the SQS message deletion process takes up to 60 seconds, so jobs sent to the SQS queue up to 60 seconds after you clear the queue might also be deleted.

キューのモニタリングMonitoring Your Queues

キューにジョブが急激に投げ込まれると、過負荷になってしまい、ジョブが完了するまでの待ち時間が長くなってしまう可能性があります。お望みなら、Laravelはキューのジョブ数が特定の閾値を超えたときに警告を出すことができます。If your queue receives a sudden influx of jobs, it could become overwhelmed, leading to a long wait time for jobs to complete. If you wish, Laravel can alert you when your queue job count exceeds a specified threshold.

使い始めるなら、queue:monitorコマンドを 毎分実行するようにスケジュールしてください。このコマンドには、監視したいキューの名前と、希望するジョブ数の閾値を指定します。To get started, you should schedule the queue:monitor command to run every minute[/docs/{{version}}/scheduling]. The command accepts the names of the queues you wish to monitor as well as your desired job count threshold:

php artisan queue:monitor redis:default,redis:deployments --max=100

このコマンドをスケジューリングするだけでは、キューの過負荷状態を警告する通知をトリガするために十分ではありません。このコマンドが、閾値を超えたジョブ数のキューと遭遇すると、Illuminate\Queue\Events\QueueBusyイベントをディスパッチします。あなたや開発チームに通知を送るために、アプリケーションのAppServiceProvider内でこのイベントをリッスンしてください。Scheduling this command alone is not enough to trigger a notification alerting you of the queue's overwhelmed status. When the command encounters a queue that has a job count exceeding your threshold, an Illuminate\Queue\Events\QueueBusy event will be dispatched. You may listen for this event within your application's AppServiceProvider in order to send a notification to you or your development team:

use App\Notifications\QueueHasLongWaitTime;
use Illuminate\Queue\Events\QueueBusy;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Notification;

/**
 * アプリケーションの全サービスの初期起動処理
 */
public function boot(): void
{
    Event::listen(function (QueueBusy $event) {
        Notification::route('mail', 'dev@example.com')
                ->notify(new QueueHasLongWaitTime(
                    $event->connection,
                    $event->queue,
                    $event->size
                ));
    });
}

テストTesting

ジョブをディスパッチするコードをテストする場合、ジョブのコードはディスパッチするコードと別に、直接テストすることができるため、ジョブ自体を実際に実行しないようLaravelへ指示したい場合があるでしょう。もちろん、ジョブそのものをテストするために、ジョブインスタンスをインスタンス化し、テスト内でhandleメソッドを直接呼び出すこともできます。When testing code that dispatches jobs, you may wish to instruct Laravel to not actually execute the job itself, since the job's code can be tested directly and separately of the code that dispatches it. Of course, to test the job itself, you may instantiate a job instance and invoke the handle method directly in your test.

Queueファサードのfakeメソッドを使用すると、キュー投入したジョブを実際にキューへプッシュされないようにできます。Queueファサードのfakeメソッドを呼び出した後で、アプリケーションがジョブをキューへ投入しようとしたことをアサートできます。You may use the Queue facade's fake method to prevent queued jobs from actually being pushed to the queue. After calling the Queue facade's fake method, you may then assert that the application attempted to push jobs to the queue:

Pest
<?php

use App\Jobs\AnotherJob;
use App\Jobs\FinalJob;
use App\Jobs\ShipOrder;
use Illuminate\Support\Facades\Queue;

test('orders can be shipped', function () {
    Queue::fake();

    // 注文発送処理…

    // ジョブが投入されないことをアサート
    Queue::assertNothingPushed();

    // 一つのジョブが指定キューへ投入されることをアサート
    Queue::assertPushedOn('queue-name', ShipOrder::class);

    // 一つのジョブが2回投入されることをアサート
    Queue::assertPushed(ShipOrder::class, 2);

    // 一つのジョブが投入されないことアサート
    Queue::assertNotPushed(AnotherJob::class);

    // クロージャがキューへ投入されることをアサート
    Queue::assertClosurePushed();

    // 投入されるジョブの合計数をアサート
    Queue::assertCount(3);
});
PHPUnit
<?php

namespace Tests\Feature;

use App\Jobs\AnotherJob;
use App\Jobs\FinalJob;
use App\Jobs\ShipOrder;
use Illuminate\Support\Facades\Queue;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function test_orders_can_be_shipped(): void
    {
        Queue::fake();

        // 注文発送処理…

        // ジョブが投入されないことをアサート
        Queue::assertNothingPushed();

        // 一つのジョブが指定キューへ投入されることをアサート
        Queue::assertPushedOn('queue-name', ShipOrder::class);

        // ジョブを2回投入することをアサート
        Queue::assertPushed(ShipOrder::class, 2);

        // 一つのジョブが投入されないことアサート
        Queue::assertNotPushed(AnotherJob::class);

        // クロージャがキューへ投入されることをアサート
        Queue::assertClosurePushed();

        // 投入されるジョブの合計数をアサート
        Queue::assertCount(3);
    }
}

指定する「真偽値テスト」にパスするジョブが、投入されたことをアサートするため、assertPushedまたはassertNotPushedメソッドへクロージャを渡せます。指定真偽値テストにパスするジョブが最低一つ投入された場合、そのアサートをパスします。You may pass a closure to the assertPushed or assertNotPushed methods in order to assert that a job was pushed that passes a given "truth test". If at least one job was pushed that passes the given truth test then the assertion will be successful:

Queue::assertPushed(function (ShipOrder $job) use ($order) {
    return $job->order->id === $order->id;
});

ジョブのサブセットのFakeFaking a Subset of Jobs

特定のジョブだけをFakeし、他のジョブは正常に実行させる必要がある場合は、fakeメソッドへ偽装するジョブのクラス名を渡してください。If you only need to fake specific jobs while allowing your other jobs to execute normally, you may pass the class names of the jobs that should be faked to the fake method:

Pest
test('orders can be shipped', function () {
    Queue::fake([
        ShipOrder::class,
    ]);

    // 注文発送処理…

    // 一つのジョブが2回投入されることをアサート
    Queue::assertPushed(ShipOrder::class, 2);
});
PHPUnit
public function test_orders_can_be_shipped(): void
{
    Queue::fake([
        ShipOrder::class,
    ]);

    // 注文発送処理…

    // 一つのジョブが2回投入されることをアサート
    Queue::assertPushed(ShipOrder::class, 2);
}

exceptメソッドを使用すると、指定したジョブセット以外のすべてのジョブをFakeできます。You may fake all jobs except for a set of specified jobs using the except method:

Queue::fake()->except([
    ShipOrder::class,
]);

ジョブチェーンのテストTesting Job Chains

ジョブチェーンをテストするには、BusファサードのFake機能を利用します。BusファサードのassertChainedメソッドは、ジョブチェーンをディスパッチしたことをアサートするために使用します。assertChainedメソッドは、最初の引数にチェーンするジョブの配列を取ります。To test job chains, you will need to utilize the Bus facade's faking capabilities. The Bus facade's assertChained method may be used to assert that a chain of jobs[/docs/{{version}}/queues#job-chaining] was dispatched. The assertChained method accepts an array of chained jobs as its first argument:

use App\Jobs\RecordShipment;
use App\Jobs\ShipOrder;
use App\Jobs\UpdateInventory;
use Illuminate\Support\Facades\Bus;

Bus::fake();

// ...

Bus::assertChained([
    ShipOrder::class,
    RecordShipment::class,
    UpdateInventory::class
]);

上の例でわかるように、ジョブチェーンの配列は、ジョブのクラス名の配列です。しかし、実際のジョブインスタンスの配列を指定することもできます。その場合、Laravelはジョブインスタンスが同じクラスであり、アプリケーションがディスパッチする同じジョブチェーンのプロパティ値を持つことを確認します。As you can see in the example above, the array of chained jobs may be an array of the job's class names. However, you may also provide an array of actual job instances. When doing so, Laravel will ensure that the job instances are of the same class and have the same property values of the chained jobs dispatched by your application:

Bus::assertChained([
    new ShipOrder,
    new RecordShipment,
    new UpdateInventory,
]);

assertDispatchedWithoutChainメソッドを使用すると、ジョブをチェーンせずに、投入したことをアサートできます。You may use the assertDispatchedWithoutChain method to assert that a job was pushed without a chain of jobs:

Bus::assertDispatchedWithoutChain(ShipOrder::class);

チェーン変更のテストTesting Chain Modifications

チェーンしたジョブが、既存のチェーンへジョブを追加または前置きしている場合、ジョブのassertHasChainメソッドを使って、そのジョブが期待通りの連鎖を持つことをアサートできます。If a chained job prepends or appends jobs to an existing chain[#adding-jobs-to-the-chain], you may use the job's assertHasChain method to assert that the job has the expected chain of remaining jobs:

$job = new ProcessPodcast;

$job->handle();

$job->assertHasChain([
    new TranscribePodcast,
    new OptimizePodcast,
    new ReleasePodcast,
]);

assertDoesntHaveChainメソッドは、ジョブの残りのチェーンが空であることをアサートするために使用します。The assertDoesntHaveChain method may be used to assert that the job's remaining chain is empty:

$job->assertDoesntHaveChain();

チェーンしたバッチのテストTesting Chained Batches

ジョブチェーンがジョブのバッチを含んでいる場合、チェーンのアサート内に Bus::chainedBatch定義を挿入することにより、チェーンしたバッチが期待値にマッチしていることをアサートできます。If your job chain contains a batch of jobs[#chains-and-batches], you may assert that the chained batch matches your expectations by inserting a Bus::chainedBatch definition within your chain assertion:

use App\Jobs\ShipOrder;
use App\Jobs\UpdateInventory;
use Illuminate\Bus\PendingBatch;
use Illuminate\Support\Facades\Bus;

Bus::assertChained([
    new ShipOrder,
    Bus::chainedBatch(function (PendingBatch $batch) {
        return $batch->jobs->count() === 3;
    }),
    new UpdateInventory,
]);

ジョブバッチのテストTesting Job Batches

BusファサードのassertBatchedメソッドは、ジョブのバッチを投入したことをアサートするために使用します。assertBatchedメソッドへ渡すクロージャは、Illuminate\Bus\PendingBatchのインスタンスを引数に取り、バッチ内のジョブを検査するために使用できます。The Bus facade's assertBatched method may be used to assert that a batch of jobs[/docs/{{version}}/queues#job-batching] was dispatched. The closure given to the assertBatched method receives an instance of Illuminate\Bus\PendingBatch, which may be used to inspect the jobs within the batch:

use Illuminate\Bus\PendingBatch;
use Illuminate\Support\Facades\Bus;

Bus::fake();

// ...

Bus::assertBatched(function (PendingBatch $batch) {
    return $batch->name == 'import-csv' &&
           $batch->jobs->count() === 10;
});

assertBatchCountメソッドを使い、指定数のバッチを投入したことをアサートできます。You may use the assertBatchCount method to assert that a given number of batches were dispatched:

Bus::assertBatchCount(3);

assertNothingBatchedを使用し、バッチを投入していないことをアサートできます。You may use assertNothingBatched to assert that no batches were dispatched:

Bus::assertNothingBatched();

ジョブ/バッチの相互操作のテストTesting Job / Batch Interaction

さらに、個々のジョブとその裏で動いているバッチとの、相互作用をテストする必要がある場合もあるでしょう。例えば、あるジョブがそのバッチの処理をキャンセルしたかをテストする必要があるかもしれません。これを実現するには、withFakeBatchメソッドでFakeバッチをジョブに割り当てる必要があります。withFakeBatchメソッドは、ジョブインスタンスとFakeバッチを含むタプルを返します。In addition, you may occasionally need to test an individual job's interaction with its underlying batch. For example, you may need to test if a job cancelled further processing for its batch. To accomplish this, you need to assign a fake batch to the job via the withFakeBatch method. The withFakeBatch method returns a tuple containing the job instance and the fake batch:

[$job, $batch] = (new ShipOrder)->withFakeBatch();

$job->handle();

$this->assertTrue($batch->cancelled());
$this->assertEmpty($batch->added);

ジョブ/キュー操作のテストTesting Job / Queue Interactions

時には、キュー投入したジョブがそれ自身をキューに戻すことをテストする必要が起きるかもしれません。あるいは、ジョブが自分自身を削除したことをテストする必要があるかもしれません。ジョブをインスタンス化してwithFakeQueueInteractionsメソッドを呼び出すことで、これらのキューとのやりとりをテストできます。Sometimes, you may need to test that a queued job releases itself back onto the queue[#manually-releasing-a-job]. Or, you may need to test that the job deleted itself. You may test these queue interactions by instantiating the job and invoking the withFakeQueueInteractions method.

ジョブのキュー操作をFakeしたら、ジョブに対して handleメソッドを呼び出してください。ジョブを呼び出した後は、assertReleasedassertDeletedassertNotDeletedassertFailedassertNotFailedメソッドを使用して、ジョブのキュー操作に対してアサートを行えます。Once the job's queue interactions have been faked, you may invoke the handle method on the job. After invoking the job, the assertReleased, assertDeleted, assertNotDeleted, assertFailed, and assertNotFailed methods may be used to make assertions against the job's queue interactions:

use App\Jobs\ProcessPodcast;

$job = (new ProcessPodcast)->withFakeQueueInteractions();

$job->handle();

$job->assertReleased(delay: 30);
$job->assertDeleted();
$job->assertNotDeleted();
$job->assertFailed();
$job->assertNotFailed();

ジョブイベントJob Events

Queueファサードbeforeおよびafterメソッドを使用して、キュー投入したジョブが処理される前または後に実行するコールバックを指定できます。これらのコールバックは、ダッシュボードの追加のログまたは増分統計を実行する絶好の機会です。通常、これらのメソッドは、サービスプロバイダbootメソッドから呼び出す必要があります。たとえば、Laravelが用意しているAppServiceProviderを使用できます。Using the before and after methods on the Queue facade[/docs/{{version}}/facades], you may specify callbacks to be executed before or after a queued job is processed. These callbacks are a great opportunity to perform additional logging or increment statistics for a dashboard. Typically, you should call these methods from the boot method of a service provider[/docs/{{version}}/providers]. For example, we may use the AppServiceProvider that is included with Laravel:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Queue;
use Illuminate\Support\ServiceProvider;
use Illuminate\Queue\Events\JobProcessed;
use Illuminate\Queue\Events\JobProcessing;

class AppServiceProvider extends ServiceProvider
{
    /**
     * 全アプリケーションサービスの登録
     */
    public function register(): void
    {
        // ...
    }

    /**
     * 全アプリケーションサービスの初期起動処理
     */
    public function boot(): void
    {
        Queue::before(function (JobProcessing $event) {
            // $event->connectionName
            // $event->job
            // $event->job->payload()
        });

        Queue::after(function (JobProcessed $event) {
            // $event->connectionName
            // $event->job
            // $event->job->payload()
        });
    }
}

Queueファサードloopingメソッドを使用して、ワーカがキューからジョブをフェッチしようとする前に実行するコールバックを指定できます。たとえば、クロージャを登録して、以前に失敗したジョブによって開いたままになっているトランザクションをロールバックすることができます。Using the looping method on the Queue facade[/docs/{{version}}/facades], you may specify callbacks that execute before the worker attempts to fetch a job from a queue. For example, you might register a closure to rollback any transactions that were left open by a previously failed job:

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Queue;

Queue::looping(function () {
    while (DB::transactionLevel() > 0) {
        DB::rollBack();
    }
});

章選択

設定

明暗テーマ
light_mode
dark_mode
brightness_auto システム設定に合わせる
テーマ選択
photo_size_select_actual デフォルト
photo_size_select_actual モノクローム(白黒)
photo_size_select_actual Solarized風
photo_size_select_actual GitHub風(青ベース)
photo_size_select_actual Viva(黄緑ベース)
photo_size_select_actual Happy(紫ベース)
photo_size_select_actual Mint(緑ベース)
コードハイライトテーマ選択

明暗テーマごとに、コードハイライトのテーマを指定できます。

テーマ配色確認
スクリーン表示幅
640px
80%
90%
100%

768px以上の幅があるときのドキュメント部分表示幅です。

インデント
無し
1rem
2rem
3rem
原文確認
原文を全行表示
原文を一行ずつ表示
使用しない

※ 段落末のEボタンへカーソルオンで原文をPopupします。

Diff表示形式
色分けのみで区別
行頭の±で区別
削除線と追記で区別

※ [tl!…]形式の挿入削除行の表示形式です。

テストコード表示
両コード表示
Pestのみ表示
PHPUnitのみ表示
OS表示
全OS表示
macOSのみ表示
windowsのみ表示
linuxのみ表示
和文変換

対象文字列と置換文字列を半角スペースで区切ってください。(最大5組各10文字まで)

本文フォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

コードフォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

保存内容リセット

localStrageに保存してある設定項目をすべて削除し、デフォルト状態へ戻します。

ヘッダー項目移動

キーボード操作