はじめに
とあるバッチ処理で、何十万件を処理するものがあり、結構重い処理になっています。それなりに処理時間がかかっていて進捗状況を確認したい時もあります。
その時は以下のようなことになっていました。
猫ちゃんの言う通りです。めんどいにゃー。もうちょっとパッと見て楽に進捗状況を確認したいですね。。。
該当のバッチは cakePHP のコンソールコマンドで実装されているので、CakePHPドキュメントを何気なく眺めていたら、「プログレスバー」機能があることに気づきました!
プログレスバーを導入すれば、パッと進捗状況も確認できそうです!
ドキュメント見てもサラッと書かれているだけなので、今回はCakePHPのプログレスバーがどんなものか試してみて、良さそうなら導入したい!
ということで、実際に試してみましょう!
- 実施環境
CakePHP:3.8
まずコンソールコマンドを作ってみよう!
ドキュメントの通り作ってみます!
<?php namespace App\Command; use Cake\Console\Arguments; use Cake\Console\ConsoleIo; use Cake\Console\Command; use Cake\Controller\ComponentRegistry; class SampleCommand extends Command { public function execute(Arguments $args, ConsoleIo $io) { // 標準出力 $io->out('サンプルだよ!'); } }
実行してみます。
$ bin/cake sample サンプルだよ!
なんともつまらないコードを書いてしまいました。
安心してください!本題はこれからですよ!
下準備のコンソールコマンドができたので、本題のプログレスバーを試してみます。
プログレスバーを使ってみよう!
ドキュメントに記載されているように実装します。
- プログレスバーの実装
executeの引数にある ConsoleIo から、Progress ヘルバーを生成します。
total に処理するファイル件数など全体の処理件数を設定します。
今回はサンプルなのでリストの件数を入れています。
// リスト件数 $total = count($check); // Progressヘルパー生成 $progress = $io->helper('Progress'); $progress->init([ // リスト件数をtotalに設定 'total' => $total, ]);
処理ループの中で、incrementにてプログレスバーのカウンターを加算していきます。
大量件数で1件毎にカウントして描画するのも無駄だったので
100件毎、1000件毎などの区切りでインクリメントするようにします。
サンプルでは100件毎に加算し、プログレスバーを描画しています。
プログレスバーの描画は「draw()」で、標準出力に表示されます。
// 100カウントで描画して、カウンターリセット if ($incrementCount === 100) { echo "【進捗状況】 "; // Progressカウンター加算 $progress->increment($incrementCount); // progress描画 $progress->draw(); // 改行 $io->out($io->nl()); $incrementCount = 0; }
全体のソースはこちらになります。
どんなものかを試してみるだけなので、サンプルリスト作って、ループで回しプログレスバーを描画するというコードですので悪しからず。
<?php namespace App\Command; use Cake\Console\Arguments; use Cake\Console\ConsoleIo; use Cake\Console\Command; class SampleCommand extends Command { public function execute(Arguments $args, ConsoleIo $io) { $check = []; $io->out('処理開始'); // ループ用のサンプルリスト for ($i=0; $i < 1030; $i++) { $check[$i] = ['test', 'テスト', 'てすと']; } // リスト件数 $total = count($check); // Progressヘルパー生成 $progress = $io->helper('Progress'); $progress->init([ 'total' => $total, ]); $io->out($io->nl()); // インクリメントカウンター $incrementCount = 0; foreach ($check as $index => $value) { $incrementCount++; // 100カウントで描画して、カウンターリセット if ($incrementCount === 100) { echo "【進捗状況】 "; // Progressカウンター加算 $progress->increment($incrementCount); // progress描画 $progress->draw(); // 改行 $io->out($io->nl()); $incrementCount = 0; } } // 最終調整(進捗100%にしたいのであふれた件数分加算し微調整) echo '【進捗状況】 '; $progress->increment($incrementCount); $progress->draw(); // 改行 $io->out($io->nl(2)); $io->out("処理終了(全{$total}件)"); } }
- プログレスバー出力結果
処理開始 【進捗状況】======> 10% 【進捗状況】=============> 19% 【進捗状況】====================> 29% 【進捗状況】============================> 39% 【進捗状況】===================================> 49% 【進捗状況】==========================================> 58% 【進捗状況】=================================================> 68% 【進捗状況】=========================================================> 78% 【進捗状況】================================================================> 87% 【進捗状況】=======================================================================> 97% 【進捗状況】==========================================================================> 100% 処理終了(全1030件)
おー!進捗状況がパッとわかりますね!
該当バッチはJenkinsを使って実行しているので、上記出力はコンソール出力を見れば確認できるので良いですね!
- プログレスバー導入決定!
これでサーバーにSSHしてログファイル見てーな地味作業がいらなくなり、Jenkinsのコンソール出力見るだけで進捗状況が確認できることがわかりました!
ということで、実際のバッチ処理にこのプログレスバーを導入することにしましたー!
終わりに
今回は、CakePHPで、大量件数処理するバッチに導入したいプログレスバーを試し、まさに求めていた機能だったので実際のバッチ処理にも導入決定しました。
自作せずとも、こういう機能が用意されていると非常に便利ですよねー。