🍡

Bref.sh で Laravel のキューを Docker イメージで動かそうとして情報が少なすぎてハマった

2022/07/07に公開

状況がいろいろ変わり 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'),
]);

余談

試行錯誤した内容

  1. LaravelSqsHandler クラスをラップして、コンストラクタやハンドラに var_dump を仕込み、 CloudWatch Logs でイベントやコンテキストが受け取れているか確認したかった
    • コンストラクタでのダンプは出来ているが、ハンドラのダンプは実行されていない
      • $app->makeWith でコンテナに入れてるときにインスタンス作るからコンストラクタは通る
      • ハンドラは SQS を動かすためのイメージを使っていなかったから呼ばれなかった
  2. Docker イメージではなく、 Lambda レイヤーを使うようにしてみた
    • 一見動いたように見えたが あらすじ の通り、すでに CI/CD 構築済みで Lambda レイヤーに対応するにはめんどうすぎた

なぜ正解にたどり着けたのか

Bref のドキュメントを読んでいて serverless.yml のサンプルのうち、コンソールコマンド用については

https://bref.sh/docs/runtimes/console.html#configuration

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 は

https://github.com/brefphp/laravel-bridge#sqs

constructs:
    jobs:
        type: queue
        worker:
            handler: worker.php
            layers:
                - ${bref:layer.php-74}

(constructs:Lift という Serverless 用のプラグイン、この例だと SQS を DLQ 込みで構築してくれる)

となっており、注目したのは layers で、コンソール用は console レイヤーを使っていますが laravel-bridge のほうは呼んでいないことに気付きました。

そして

https://github.com/brefphp/bref/tree/master/runtime/layers

console, function などでブートストラップで行っていることが違うことに気づき、「コンソール用のイメージを使うのが間違っているのでは」と相成ったわけです。

「Laravel のキューを使う」 イコール Artisan を使う、だから「コンソールを使う」という先入観が敗因でした。

Discussion