シンプルなPHPタスクスケジューラ

画像

多かれ少なかれ大規模なプロジェクトの進化の過程で、スケジュールされたタスク(cronジョブ)の数が非常に多くなり、サポートがdevopsにとって悪夢になるような状況が発生する場合があります。 この問題を解決するために、PHPでスケジューラー実装を作成し、それをプロジェクトの一部にし、タスク自体-その構成の一部にするというアイデアに思いつきました。 この場合、必要かつ十分なcronジョブの数は1に等しくなります。







しばらく前に、偶然イベント企画のためのモジュールを開発しました。 アプリケーションのユーザー向けのある種の単純化された類似性Google / Appleカレンダー。 繰り返しイベントの日付とルールを保存するために、iCalendar形式( RFC 5545 )を使用することが決定されました。これは、曜日、月、繰り返し数などを考慮したイベントの繰り返しスケジュールの1行の記述を可能にします。 いくつかの例:







FREQ=WEEKLY;BYDAY=SU,WE



毎週土曜日と水曜日

FREQ=MONTHLY;COUNT=5



毎月5回

FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU



- FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU



、1月の毎週土曜日







ご覧のとおり、この標準を使用すると、cronが提案するよりもはるかに柔軟にイベントを繰り返すためのルールを記述できます。







iCalendar形式で作業するための素晴らしいライブラリが見つかりました(スターを後悔しないでください):

https://github.com/simshaun/recurr







RRULE(繰り返しルール)を操作するためのツールがあるので、問題は小さいままです。 タスク(PHP callable



タイプの明示)を計画および実行できるクラスをいくつか作成します。







ライブラリのインストール:



composer require hutnikau/job-scheduler









タスクのスケジューリングと起動:



\Scheduler\Job\Job



-タスクを表すクラス







インスタンスを作成するには、その繰り返しルール(RRULE)とcallable



タイプのインスタンスが必要です。







 $startTime = new \DateTime('2017-12-12 20:00:00'); $rule = new \Scheduler\Job\RRule('FREQ=MONTHLY;COUNT=5', $startTime); //run monthly, at 20:00:00 starting from the 12th of December 2017, 5 times $job = new \Scheduler\Job\Job($rule, function () { //do something });
      
      





別の方法は、 \Scheduler\Job\Job::createFromString()



を使用することです。







 $job = \Scheduler\Job\Job::createFromString( 'FREQ=MONTHLY;COUNT=5', //Recurrence rule '2017-12-28T21:00:00', //Start date function() {}, //Callback 'Europe/Minsk' //Timezone. If $timezone is omitted, the current timezone will be used );
      
      





タイムゾーンを忘れないでください。 不愉快な驚きを避けるために、これらを常に明示的に指定することを強くお勧めします(このライブラリで作業するときだけでなく、一般的に\DateTime



でも)。







タスクをスケジューラに追加します。







 $scheduler = new \Scheduler\Scheduler() $scheduler->addJob($job);
      
      





タスクの配列をコンストラクターに渡すこともできます。







 $scheduler = new \Scheduler\Scheduler([ $job, //more jobs here ])
      
      





スケジュールされたタスクを実行します。







 $jobRunner = new \Scheduler\JobRunner\JobRunner(); $from = new \DateTime('2017-12-12 20:00:00'); $to = new \DateTime('2017-12-12 20:10:00'); $reports = $jobRunner->run($scheduler, $from, $to, true);
      
      





この例では、指定された期間(10分)にスケジュールされたすべてのタスクが完了します。 したがって、 JobRunner



実行するcronジョブは1つだけ必要JobRunner









$to



パラメータを省略すると、 $to



現在$from



すべてのタスクが実行されます。







最後のパラメーターは、実行時間が境界値(上記の例の「2017-12-12 20:00:00」および「2017-12-12 20:10:00」)に正確に一致するタスクを完了するかどうかを決定します。







cronを使用してスケジューラーを開始する場合、cronの精度は理想的ではないため、最後の開始時間を保存し、次の開始時に$from



パラメーターに渡すことをお勧めします。タスクをスキップしたり、2回実行したりすることができます。







$jobRunner->run(...)



は、完了したタスクの結果の配列(タイプ\Scheduler\Action\Report



のオブジェクトの配列$jobRunner->run(...)



返します。







 \Scheduler\Action\Report { /* Methods */ public mixed getReport ( void ) public Action getAction ( void ) public string getType ( void ) }
      
      





\Scheduler\Action\Report::getReport()



呼び出すことにより、呼び出し可能な結果(それによって返される値\Scheduler\Action\Report::getReport()



を取得できます。







タスクの実行中に例外がスローされた場合、 \Scheduler\Action\Report::getReport()



は同じ例外を返します。







\Scheduler\Action\Report::getAction()



は、実行されたアクションを記述する\Scheduler\Action\ActionInterface



インスタンスを返します。 これを使用すると、アクションの実行時間を確認したり、アクション自体を取得したりできます(ジョブ)。







また、スケジュールされたタスクが複数回実行される場合(たとえば、RRULEでMINUTELY間隔が使用され、 MINUTELY



$to



渡される$from



$to



toのJobRunner



10分だった場合)、アクションが数回実行されることにも注意してください。 つまり、グループ化されません。







おそらくそれだけです。 ライブラリは本当に小さいですが、誰かに役立つことを願っています。

建設的な批判と開発援助は大歓迎です。







Github

パカギスト








All Articles