9️⃣
Laravel Queues
- Laravel Queuesからの抜粋
- connection は "database" のみ。Redis や Amazon SQS はよく解らない
最も単純な構成
1. Job を作成
- artisan コマンドでクラスを作成
php artisan make:job ProcessPodcast
- クラスに処理を記述App/Jobs/ProcessPodcast.php
public function __construct( public Podcast $podcast, ) {} public function handle(): void { logger("Job を実行 {$this->podcast->name}"); }
2. Job を Queue に入れる
- Controller などで dispatch するApp/Http/Controllers/Controller/PodcastController.php
public function store(Request $request): RedirectResponse { $podcast = Podcast::create(/* ... */); ProcessPodcast::dispatch($podcast); return redirect('/podcasts'); }
-
jobs にレコードが登録される
3. Job を実行する
- artisan コマンドで実行する
php artisan queue:work
- Jobが成功した場合、jobs からレコードは削除される
- Jobが失敗した場合、failed_jobs に記録される
4. Job を修正する
- Job の内容を修正した場合、queue を再起動する
php artisan queue:restart
複数の Queue を扱う
-
queue の名前を指定しない場合、"default" が適用される
-
Job もしくは dispatch 時に queue を指定できる
App/Jobs/ProcessPodcast.phppublic function __construct( public Podcast $podcast, ) { $this->onQueue('processingPodcast'); }
App/Http/Controllers/Controller/PodcastController.phppublic function store(Request $request): RedirectResponse { $podcast = Podcast::create(/* ... */); ProcessPodcast::dispatch($podcast)->onQueue('processingPodcast'); return redirect('/podcasts'); }
-
Job を実行する際には Queue 名を指定する(指定した順に優先度高)
php artisan queue:work --queue=processingPodcast,default
複数種類のJobを連続して実行する
- Job Chaining
- dispatch 時に Chain を構成するApp/Http/Controllers/Controller/PodcastController.php
use App\Jobs\Job1; use App\Jobs\Job2; use Illuminate\Support\Facade\Bus; public function store(Request $request): RedirectResponse { $podcast = Podcast::create(/* ... */); Bus::chain([ new Job1($podcast), new Job2(), ])->onQueue('processingPodcast')->dispatch(); ProcessPodcast::dispatch($podcast)->onQueue('processingPodcast'); return redirect('/podcasts'); }
- 先行する Job が失敗した場合、後続する Job は実行されない
- 実行される Queue について
- onQueue で指定した Queue
- 各 Job クラスで指定した Queue ← こちらが優先
タイムアウト
- Timeout
- デフォルトのタイムアウトは 60 秒
- Job の属性もしくは artisan コマンドで指定するApp/Jobs/ProcessPodcast.php
public $timeout = 120;
php artisan queue:work --timeout=30
Commitの待機
- Specifying Commit Dispatch Behavior Inline
- dispatch するためにトランザクションの終了を待つか待たないか指定する
- 親を含むすべてのトランザクションが対象となる
- config もしくは、dispatch 時に指定することができるconfig/queue.php
`database` => [ 'after_commit' => true, ]
App/Http/Controllers/Controller/PodcastController.phppublic function store(Request $request): RedirectResponse { $podcast = Podcast::create(/* ... */); ProcessPodcast::dispatch($podcast)->afterCommit(); return redirect('/podcasts'); }
- トランザクションが rollback された場合、トランザクション中に dispatch された Job は破棄されるApp/Http/Controllers/Controller/PodcastController.php
public function store(Request $request): RedirectResponse { DB::transaction(function () { $podcast = Podcast::create(/* ... */); ProcessPodcast::dispatch($podcast); throw new \Exception("test"); }); return redirect('/podcasts'); }
その他
-
Queued Relationships
- Job に引き渡した Eloquent モデルのリレーションの扱いについて
-
Unique Jobs
- 同じ Job を同時に Queue に追加したくない
- 実行間隔の指定、同一判定の実装を追加する
-
Job Middleware
- Routing の Middleware と同じ仕組み
- 各 Job に共通の処理(レート制限など)を差し込む用途
- レート制限は標準の実装がある
Discussion