前提
Laravelのバージョン:11.20.0
キューの内容はDBに保存する設定で、必要なテーブルもマイグレートされていることを前提とする。
(デフォルトの状態でマイグレートすればそうなっているはず)
全体的な注意点としてジョブや他のファイルを変更した後、
キューワーカを再起動することを忘れずに。
準備
ジョブの作成
次のコマンドでキューに入れるジョブを作成する。
php artisan make:job TestJob
作成されたTestJobクラスのhandleメソッドを次のように編集する。
public function handle(): void
{
Log::info('TestJob');
}
動作確認用コントローラの作成
次のコマンドで今回の動作確認用のコントローラを作成する。
php artisan make:controller Test
作成されたTestコントローラに次のメソッドを追記する。
public function TestJob()
{
TestJob::dispatch();
return view('welcome');
}
ルーティングの設定
routes/web.phpにて、デフォルトのルートをコメントアウトし、(削除しても良い)
次のように編集する。
//Route::get('/', function () {
// return view('welcome');
//});
Route::get('/', [\App\Http\Controllers\Test::class, 'TestJob']);
シンプルな動作確認
目的
ジョブをキューに入れて、
DBがどうなっているのかを見て、
キューに入れたジョブがどう実行されるのか確認する。
ジョブをキューへ入れる。
http://localhost へ1回アクセスして、次のSQLを実行する。
SELECT * FROM jobs;
次のような結果が得られるはず。
id | queue | peyload | attempts | reserved_at | available_at | created_at |
数字 | default | {“uuid”:”bb78e2f3-13e5-4535-af52-645f2b65b4c0″,”displayName”:”App\\Jobs\\TestJob”,”job”:”Illuminate\\Queue\\CallQueuedHandler@call”,”maxTries”:null,”maxExceptions”:null,”failOnTimeout”:false,”backoff”:null,”timeout”:null,”retryUntil”:null,”data”:{“commandName”:”App\\Jobs\\TestJob”,”command”:”O:16:\”App\\Jobs\\TestJob\”:0:{}”}} | 0 | null | 1745073256 | 1745073256 |
available_atとcreated_atの値はUNIXタイムスタンプなので、変換して見てもらいたいが、available_atとcreated_atの値が同一であることを見れば何となく用途がわかるはず。
このjobsテーブルへ上記のようなデータがあれば、作成されたジョブがキューに入ったと確認できる。
キューに入っているジョブを実行する
キューワーカを起動するために次のコマンドを実行すれば良い。
php artisan queue:work
次のように画面にジョブが実行された旨が表示される。
INFO Processing jobs from the [default] queue.
2025-04-19 15:17:05 App\Jobs\TestJob ........................................................... RUNNING
2025-04-19 15:17:05 App\Jobs\TestJob ...................................................... 18.12ms DONE
また、ログファイル(storage/logs/laravel.log)を見ると次のようなログが記録されている。
[2025-04-19 15:17:05] local.INFO: TestJob
jobsテーブルを先ほどのSQLで確認すると、データは無くなっている。
キューワーカが実行中にジョブをキューに入れる
上記のartisanコマンドが実行され続けていることを確認して、
再度http://localhostへアクセスし、
ジョブをキューへ格納すると即実行されることを確認すれば良い。
レート制限の動作確認
試した中では2パターンの使い方ができそう。
- 1. 指定した時間を経過するたびにキュー内のジョブを1個実行する。ただし、キュー内のジョブの数を把握する必要がある。
- 2. 指定した時間を経過しないとキューへジョブを追加できないようにする。キューへ追加されたジョブは即実行される。
1番目の指定した時間を経過するたびにキュー内のジョブを1個実行する場合の例
前提:上記のシンプルな動作確認の内容を流用する。
TestJob.php の内容を次のように編集する。
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Queue\Middleware\RateLimited;
use Illuminate\Support\Facades\Log;
class TestJob implements ShouldQueue
{
use Queueable;
public $tries = 0;
/**
* Create a new job instance.
*/
public function __construct()
{
//
}
/**
* Execute the job.
*/
public function handle(): void
{
Log::info('TestJob' . mt_rand(10, 20));
}
public function middleware(): array
{
return [(new RateLimited('TestJob1min'))];
}
}
app/Providers/AppServiceProvider.php の内容を次のように編集する。
<?php
namespace App\Providers;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
RateLimiter::for('TestJob1min', function() {
// 15秒に1回しか許可しない。
return Limit::perSecond(1, 15);
});
}
}
上記内容でhttp://localhostへ3回アクセスすると、
各ジョブの処理が15 + α秒で実行されていることが確認できる。
2番目の指定した時間を経過しないとキューへジョブを追加できないようにする場合の例
前提:上記のシンプルな動作確認の内容を流用する。
前提2:上記のAppServiceProvider.php の内容を流用する。
TestJob.php の内容を次のように編集する。
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Queue\Middleware\RateLimited;
use Illuminate\Support\Facades\Log;
class TestJob implements ShouldQueue
{
use Queueable;
/**
* Create a new job instance.
*/
public function __construct()
{
//
}
/**
* Execute the job.
*/
public function handle(): void
{
Log::info('TestJob' . mt_rand(10, 20));
}
public function middleware(): array
{
return [(new RateLimited('TestJob1min'))->dontRelease()];
}
}
上記内容でhttp://localhostへ15秒以内に3回アクセスすると、
ジョブは1個しか実行されず、キュー内(jobsテーブル)のジョブは0個となっていることが確認できる。
その15秒後に再度アクセスすると、ジョブはまた1個実行されることが確認できる。
一意なジョブの動作確認
キュー内で$uniqueIdが指定されたジョブがある場合、同一の$uniqueIdを持つジョブを新たに追加できなくなることを確認する。
(キュー内で$uniqueIdが指定されたジョブは、$uniqueIdに基づいて一意のものとなる。)
レート制限の動作確認の
1番目の指定した時間を経過するたびにキュー内のジョブを1個実行する、を流用して確認する。
TestコントローラのTestJobメソッドの内容を次のように編集する。
public function TestJob(Request $request)
{
TestJob::dispatch(100);
return view('welcome');
}
TestJob.php の内容を次のように編集する。
ShouldBeUniqueのインターフェイスを追加している点に注意。
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Queue\Middleware\RateLimited;
use Illuminate\Support\Facades\Log;
class TestJob implements ShouldQueue, ShouldBeUnique
{
use Queueable;
public $tries = 0;
public $uniqueId;
/**
* Create a new job instance.
*/
public function __construct(int $intValue)
{
Log::info("TestJob Constructor \$intValue = {$intValue}");
$this->uniqueId = $intValue;
}
/**
* Execute the job.
*/
public function handle(): void
{
Log::info('TestJob' . mt_rand(10, 20));
}
public function middleware(): array
{
return [(new RateLimited('TestJob1min'))];
}
}
上記内容でhttp://localhostへ15秒以内に3回以上アクセスしても、
ジョブは2回しか実行されないことが確認できる。
1回目はキューへ入れた瞬間実行され、
2回目は一意であるためキューへ入れることができ、
3回目以降は$uniqueIdが同一であるジョブが、キュー内に存在するためキューへ入れることができない。
Tips
キュー内のジョブ数を取得
DBから直接取得しても良いかもしれない。
use Illuminate\Support\Facades\Queue;
Queue::size('default');
ジョブに設定したuniqueIdを取得
DBから引っ張るやり方になる。
キューに1個のジョブがある状態で実行する例。
$dbResult = DB::table('jobs')->select('payload')->get();
$uniqueId = unserialize(json_decode($dbResult->all()[0]->payload)->data->command)->uniqueId;