🍡
Bref.sh で Laravel のキューを Docker イメージで動かそうとして情報が少なすぎてハマった
状況がいろいろ変わり PHP を Lambda で動かす機会が減りそうなちゃちいです。
あらすじ
- PHP(Laravel) を Lambda で動かしている
- Lambda レイヤーだとサイズを超える恐れがあるため Docker イメージで動かしている
- Docker イメージをビルドするように CI/CD は構築済み
- Web App(API), EventBridge 起点の
php artisan schedule:run
がある - そんな中、キューが必要になった
- Laravel のキューを使う
どこでハマった?
- コンソール用イメージをキューワーカーでも使えると思って
FROM bref/php-81-console
を指定していた
解決策
-
FROM bref/php-81
とする - ハンドラとなる PHP の実装はドキュメント通りでOK
FROM bref/php-81
COPY . /var/task
CMD [ "worker.php" ]
<?php
declare(strict_types=1);
use Bref\LaravelBridge\Queue\LaravelSqsHandler;
use Illuminate\Foundation\Application;
require __DIR__ . '/vendor/autoload.php';
/** @var Application $app */
$app = require __DIR__ . '/bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$kernel->bootstrap();
return $app->makeWith(LaravelSqsHandler::class, [
'connection' => 'sqs',
'queue' => getenv('SQS_QUEUE'),
]);
余談
試行錯誤した内容
-
LaravelSqsHandler
クラスをラップして、コンストラクタやハンドラにvar_dump
を仕込み、 CloudWatch Logs でイベントやコンテキストが受け取れているか確認したかった- コンストラクタでのダンプは出来ているが、ハンドラのダンプは実行されていない
-
$app->makeWith
でコンテナに入れてるときにインスタンス作るからコンストラクタは通る - ハンドラは SQS を動かすためのイメージを使っていなかったから呼ばれなかった
-
- コンストラクタでのダンプは出来ているが、ハンドラのダンプは実行されていない
- Docker イメージではなく、 Lambda レイヤーを使うようにしてみた
- 一見動いたように見えたが あらすじ の通り、すでに CI/CD 構築済みで Lambda レイヤーに対応するにはめんどうすぎた
なぜ正解にたどり着けたのか
Bref のドキュメントを読んでいて serverless.yml
のサンプルのうち、コンソールコマンド用については
functions:
hello:
handler: bin/console # or 'artisan' for Laravel
layers:
- ${bref:layer.php-74} # PHP runtime
- ${bref:layer.console} # Console layer
となっており、かたや Bref を Laravel で使えるようにする brefphp/laravel-bridge の README.md は
constructs:
jobs:
type: queue
worker:
handler: worker.php
layers:
- ${bref:layer.php-74}
(constructs:
は Lift という Serverless 用のプラグイン、この例だと SQS を DLQ 込みで構築してくれる)
となっており、注目したのは layers
で、コンソール用は console
レイヤーを使っていますが laravel-bridge のほうは呼んでいないことに気付きました。
そして
の console
, function
などでブートストラップで行っていることが違うことに気づき、「コンソール用のイメージを使うのが間違っているのでは」と相成ったわけです。
「Laravel のキューを使う」 イコール Artisan を使う、だから「コンソールを使う」という先入観が敗因でした。
Discussion