外部システムから投入されるSQSキューをLaravelで監視処理する

# はじめに

[Laravelのキュー](https://readouble.com/laravel/6.x/ja/queues.html)はLaravelから投入してLaravelで処理する前提になっているので、そのままだと外部の仕組みから投入したメッセージを処理することはできません。

https://laravel.io/forum/02-03-2014-help-with-setting-up-a-queue-listener

この投稿にあるように、`{"job":"Acme\\Jobs\\PushFilesJob","data":{"file_id":"1"}}`のようなJSON形式で送信されていないとキューの中身とジョブの紐づけができないからです。

このフォーマットで送ってくれるならいいですが、外部の仕組みだとそうもいかないことがほとんどだと思います。

そこでなんか方法ないかと調べたところよさげなプラグインを発見。

https://github.com/dusterio/laravel-plain-sqs

ただ、README.mdがなかなか不親切だったため導入に難儀したので手順を残します。
Laravel6系で試しています。

# インストール

Composerでインストール。

```
>composer require dusterio/laravel-plain-sqs
>composer require aws/aws-sdk-php-laravel
```

```php:/config/app.php
    'providers' => [

        // ～中略～

        /*
         * Package Service Providers...
         */
        Dusterio\PlainSqs\Integrations\LaravelServiceProvider::class,
        Aws\Laravel\AwsServiceProvider::class,
```

# 設定

ライブラリの設定ファイルをpublishします。

```
>php artisan vendor:publish --provider Dusterio\PlainSqs\Integrations\LaravelServiceProvider
Copied File [\vendor\dusterio\laravel-plain-sqs\src\config\sqs-plain.php] To [\config\sqs-plain.php]
Publishing complete.
```

ライブラリの設定ファイルに呼び出したいジョブのクラスを指定。
`handlers`を使うとキュー名に対応したジョブを呼び出せるそう。

```php:/conifg/sqs-plain.php
<?php

/**
 * List of plain SQS queues and their corresponding handling classes
 */
return [
    'handlers' => [
        'foo-queue' => App\Jobs\BarJob::class,
    ],

    'default-handler' => App\Jobs\SampleJob::class
];
```

キューの設定ファイルに`laravel-plain-sqs`用の情報を追加。

```php:/config/queue.php
        'sqs' => [
            'driver' => 'sqs',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
            'queue' => env('SQS_QUEUE', 'your-queue-name'),
            'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
        ],

        'sqs-plain' => [
            'driver' => 'sqs-plain',
            'key'    => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
            'queue'  => env('SQS_QUEUE', 'your-queue-name'),
            'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
        ],
```

`.env`にAWSリソースの情報追加。
あらかじめSQSキューとアクセスできるIAMが用意されてる前提です。

```.env
QUEUE_CONNECTION=sqs-plain

AWS_ACCESS_KEY_ID=*****************
AWS_SECRET_ACCESS_KEY=*******************************************
AWS_DEFAULT_REGION=ap-northeast-1
SQS_PREFIX=https://sqs.ap-northeast-1.amazonaws.com/999999999999
SQS_QUEUE=MyQueue
```

# ジョブの作成

キューのメッセージを受信して処理するジョブを作成します。
Readme.mdそのままだと動かせなかったのでこちらの[イシュー](https://github.com/dusterio/laravel-plain-sqs/issues/40)を参考に（マージしてほしい…）。

```
>php artisan make:job SampleJob
```

```php:/app/Jobs/SampleJob.php
<?php

namespace App\Jobs;

use Illuminate\Queue\Jobs\Job;
use Illuminate\Support\Facades\Log;

class SampleJob extends Job
{
    /**
     * Execute the job.
     * @param Job $job
     * @param array $data
     */
    public function handle(Job $job, array $data)
    {
        // This is incoming JSON payload, already decoded to an array
        Log::info($data);
        // Raw JSON payload from SQS, if necessary
        Log::info($job->getRawBody());
    }

    public function getRawBody() {}
    public function getJobId() {}
}
```

# 動作確認
ワーカーを起動させて、キューにデータを投入します。

```
>php artisan queue:work
[2021-11-14 15:13:05][f8984da8-6cb7-4d1c-a328-f4c1b850679c] Processing: App\Jobs\SampleJob@handle
[2021-11-14 15:13:05][f8984da8-6cb7-4d1c-a328-f4c1b850679c] Processed:  App\Jobs\SampleJob@handle
```

`{"foo":1,"bar":true}`
適当なJSONを送ってみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/446dc94c-b134-c283-bf0d-912356eab538.png)

```/storage/logs/laravel.log
[2021-11-14 15:13:05] local.INFO: array (
  'foo' => 1,
  'bar' => true,
)  
[2021-11-14 15:13:05] local.INFO: {"job":"App\\Jobs\\SampleJob@handle","data":{"foo":1,"bar":true},"uuid":"f8984da8-6cb7-4d1c-a328-f4c1b850679c"}  
```