用途としては即レスポンスを返して裏でログ登録をしたいときなど。
コマンド呼び出して非同期に実行する
1 | exec ( 'nohup php -c xxxx.php > /dev/null &' ); |
phpを実行する処理を行う。
簡単だがライブラリのパス周りの解決方法がわからなかった。
Laravelのキューを使用する
https://readouble.com/laravel/5.7/ja/queues.html
キューを登録するためのテーブルが必要。
php artisan queue:table
php artisan migrate
php artisan migrate
ジョブ作成
php artisan make:job JobTest
ShouldQueueを継承したクラスがapp/Jobs以下に作成される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class JobTest implements ShouldQueue { /** * 最大試行回数 * * @var int */ public $tries = 1; protected $id ; protected $text ; public function __construct( $map ) { $this ->id = $map [ 'id' ]; $this ->text = $map [ 'text' ]; } public function handle() { // ログを追加する addlog( $this ->id, $this ->text) } } |
デフォルトだと失敗したときに再施行するので$triesを1に設定する。
コンストラクタには0~1つの引数を渡せる。複数渡したい場合クラスか連想配列を渡す。
キュー実行時handleメソッドが実行される。
ジョブ呼び出し処理
1 | JobTest::dispatch( array ( 'id' => "0001" , 'text' => "test message" )); |
JobTestクラスのコンストラクタが呼び出された後handleメソッドが実行される。
引数は一つなので手っ取り早く実装したいなら連想配列を渡す。
.env修正
jobの登録先を設定する。DBならほぼ使用しているはずなので手っ取り早いか。
QUEUE_DRIVER=database
以上で実装は完了だが一つ問題がありキューを処理するためには
php artisan queue:work
でワーカーを立ち上げなければいけない。本番で使用する場合再起動時にコマンドが実行されるようにしないといけない。
やりたいことはこういうことではない。
そこでキューを登録した後以下のスニペットを追記する。
1 2 3 | JobTest::dispatch( array ( 'id' => "0001" , 'text' => "test message" )); $cmd = "nohup php " . base_path() . "/artisan queue:work --once > /dev/null &" ; exec ( $cmd ); |
これで1回のみ非同期ジョブを処理することができる。
終了時にはプロセスがkillされる。
ただ呼び出されるたびにプロセスが立ち上がるのは少々気になる。
ジョブが多すぎる場合問題が出るかもしれない。