キュー

Laravelでは標準でジョブキューを使用することができます。ジョブキューを使って、時間の掛かる処理を非同期で実行することができます。簡単なサンプルを作って、実際に試してみたいと思います。


ドライバー

Laravel5で利用できるキューのドライバーは以下の6種類あります。

  • sync: デフォルト設定で、実際には同期処理として動きます
  • database: データベースをジョブキューとして使います
  • beanstalkd: beanstalkd オープンソースのジョブキューです
  • sqs: Amazon Simple Queue Service 有料サービスです
  • iron: ironMQ 有料サービスです
  • redis: Redis オープンソースのKVSです

今回はすぐに使える database を使ってキューを試します。


環境設定

キューの設定で使用するファイルは以下の2ファイルです。

  • .env
  • config/queue.php
// .env

QUEUE_DRIVER=database

キュードライバーに database を指定

<?php // config/queue.php

return [
	'default' => env('QUEUE_DRIVER', 'sync'),  // ①

	'connections' => [

		'sync' => [
			'driver' => 'sync',
		],

		'database' => [  // ②
			'driver' => 'database',
			'table' => 'jobs',
			'queue' => 'default',
			'expire' => 60,
		],

		// ...
	],

	'failed' => [  // ③
		'database' => 'mysql', 'table' => 'failed_jobs',
	],
];

① キュードライバーは .env ファイルを参照して設定されます。

② データベースドライバーの設定
jobsテーブルにジョブがキューイングされます。

③ 失敗したジョブの格納先の設定
デフォルトは mysql データベースの failed_jobs テーブルになっています。


マイグレーション

database キュードライバーを使用するには、ジョブを記録するためのテーブルが必要です。artisan コマンドで作成します。

php artisan queue:table
php artisan queue:failed-table

php artisan migrate

ジョブの作成

キューに登録するジョブはジョブクラスとして作成する必要があります。artisan で作成します。 –queued オプションを付けるのを忘れないでください。

php artisan make:job SendReminderEmail --queued

コマンドクラスは app/Commands ディレクトリに作成されます。
コンストラクタと handle() メソッドが空で作成されるので、下記のように編集します。

<?php // app/Jobs/SendReminderEmail.php

namespace App\Jobs;

use App\Jobs\Job;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Bus\SelfHandling;
use Illuminate\Contracts\Queue\ShouldQueue;

// 追加
use App\User;
use Illuminate\Contracts\Mail\Mailer;

class SendReminderEmail extends Job implements SelfHandling, ShouldQueue
{
    use InteractsWithQueue, SerializesModels;

    protected $user; // 追加

    public function __construct(User $user) // ①
    {
        $this->user = $user;
    }

    public function handle(Mailer $mailer) // ②
    {
        $mailer->send('email.remainder', ['user' => $this->user], function($message) {
            $message->to($this->user->email, $this->user->name)->subject('お知らせ');
        });
    }
}

① コンストラクタで、このコマンドに必要なデータを受け取ります。

② handle() メソッドで、このコマンドがやることを実装します。
handle() では、依存をタイプヒントで指定でき、サービスコンテナが自動的に注入してくれます。ここでは Mailer を依存注入しています。


ウェルカムメール

コマンドの中で送信しているウェルカムメールを作成します。

{{-- resources/views/emails/reminder.blade.php --}}

<p>
    {{ $user['name'] }} さん
</p>

<p>
    本日のスケジュールチェックをお忘れなく!
</p>

キューへのジョブ投入

コントローラを作成します。

php artisan make:controller UsersController --plain

app/Http/Controllers/UsersController.php を以下のように編集します。

<?php

namespace App\Http\Controllers;

use App\User;
use App\Jobs\SendReminderEmail;
use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;

class UsersController extends Controller
{
    public function SendReminderEmail(Request $request, $id)
    {
        $user = User::findOrFail($id);

        $this->dispatch(new SendReminderEmail($user)); // ①

        return "リマインダーメールを送りました。";
    }
}

① ジョブをキューに投入するには、 コントローラのdispatch() メソッドを使います。
引数にはコマンドクラスを生成して渡します。

routes.php を以下のように編集します。

// app/Http/routes.php

...

Route::get('reminder/{id}', 'UsersController@SendReminderEmail'); // 追加

コントローラを作成せずに以下のように実装することも可能です。

// app/Http/routes.php

...

use App\Jobs\SendReminderEmail;

Route::get('reminder/{id}', function ($id) {
    $user = User::findOrFail($id);

    Queue::push(new SendReminderEmail($user)); // ①

    return "リマインダーメールを $user->name に送りました";
});

① Queue::push()でジョブをキューイングすることができます。


キューの確認

では、実際に下記のURLにアクセスして動きを確かめてみます。
※ユーザは予め登録しておいてください。

http://localhost:8000/reminder/1

アクセスするとすぐに以下のメッセージが表示されますが、ジョブはキューの中にあり、ユーザへは、まだメールされていません。

リマインダーメールを送りました。

データベースの jobs テーブルを確認してみます。

> select * from jobs;
          id = 1
       queue = default
     payload = {"job":"Illuminate\\Queue\\CallQueuedHandler@call","data":{"command":"O:26:\"App\\Jobs\\SendReminderEmail\":4:{s:7:\"\u0000*\u0000user\";O:45:\"Illuminate\\Contracts\\Database\\ModelIdentifier\":2:{s:5:\"class\";s:8:\"App\\User\";s:2:\"id\";s:1:\"1\";}s:5:\"queue\";N;s:5:\"delay\";N;s:6:\"\u0000*\u0000job\";N;}"}}
    attempts = 0
    reserved = 0
 reserved_at = 
available_at = 1435260914
  created_at = 1435260914

1件、ジョブが登録されています。


キューリスナー

キューの中のジョブを実行するには、キューリスナーを動かす必要があります。

php artisan queue:listen

少しすると、リマインダーメールが送信され、データベースの jobs テーブルからジョブが削除されます。
queue:listen は一度起動すると、手動で停止(ターミナルで ^C)しないと、動き続けます。

キューの最初のジョブだけ実行したい場合は、queue:work を使います。

php artisan queue:work

※リマインダーメールが送信されない場合は何らかのエラーが発生しているので、storage/logs/*.logを確認してください。


まとめ

簡単なサンプルでキューを使うための一連の流れが理解出来ました。
時間の掛かる処理は非同期とすることで、ユーザーへのレスポンスを素早く返すことができます。有効に利用していきましょう。

また、今回はキューの詳細は取り上げていないので、公式サイトのドキュメントを確認するようにしてください。
http://laravel.com/docs/5.1/queues

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中