Magento2のCronジョブとは
この記事は公開から 1年以上が経過しています。現在の最新情報との整合性については弊社では一切の責任を負いかねます。
Magento1の時代からMagentoを触っている人にとっては、MagentoがCronによる定時バッチで様々なデータを更新・処理していることはよく知られていることはないでしょうか。
もちろんMagento2にもCronの仕組みはありますが、Magento1よりもいろいろと改善されています。
今回はMagento2のCronについて取り上げたいと思います。
Cronジョブは正しくセットアップしないと動かない
公式のDevDocsにも書かれていますが、Magentoのインストール後にはCronジョブを正しくセットアップする必要があります。
Magento2は原則Linuxサーバー上で動かす前提で作られているので、Linuxサーバーの設定に慣れている方であれば、Cronジョブの定義はさほど難しくはないでしょう。
Devdocsに示されている定義例をもとに、お使いの環境に合わせて定義を行ってください。
Cronジョブの作り方
Magentoのカスタマイズを進める上で、Cronジョブの作り方を知っていると、外部システム連携が行いやすくなります。
ここでは既に何かしらの独自エクステンションがある前提で説明を進めます。Magentoのエクステンション作成については他の記事を参照してください。
XMLファイルの定義
最初にXMLファイルを定義しておきます。
Cronジョブを定義する場合は、エクステンションディレクトリ内に「etc/crontab.xml」を作成します。
(既にある場合は定義を追記します)
XMLの内容は概ね決まっていて、以下のように定義します。
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd"> <group id="default"> <job name="example_job" instance="My\Example\Cron\Example" method="execute"> <schedule>*/5 * * * *</schedule> </job> </group> </config>
複数のジョブを定義したい場合は、jobタグを複数定義します。
ただし、jobタグはgroupタグの子要素と決まっているので、XSDが定義していない場所にタグを書いてはいけません。
Cronジョブを担当するクラスの作成
続いて、ジョブを担当するクラスを作成します。
先程crontab.xmlで定義したクラス名のモジュールを作成します。
namespace My\Example\Cron; class Example { public function execute() { ... 具体的な処理 } }
コンストラクタやその他のメソッドは必要に応じて調整してください。
ObserverやPluginの場合は呼び出し元やフック元から渡されるパラメータがありますが、Cronの場合は何も渡されないので、処理目的に合わせたクラスをコンストラクタで定義する必要があります。
(このあたりはMagento2のDependency Injectionの仕組みを理解するとわかります)
Cronグループとは
Magento2から導入された概念として「Cronグループ」というものがあります。
Magento1では、1つのCronジョブが長時間処理を続けてしまうと、後続するジョブがすべて遅延するという問題がありました。
Magento2では、Cronグループが導入されたことで、ジョブを任意のグループに分けることができるようになり、処理に時間を要するジョブを独立して実行することができるようになりました。
Cronグループの定義
Cronグループを定義するには、crontab.xmlと同じ場所に、「cron_groups.xml」を作成し、以下のような内容を書き込みます。
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/cron_groups.xsd"> <group id="my_cron_group"> <schedule_generate_every>1</schedule_generate_every> <schedule_ahead_for>4</schedule_ahead_for> <schedule_lifetime>2</schedule_lifetime> <history_cleanup_every>10</history_cleanup_every> <history_success_lifetime>10</history_success_lifetime> <history_failure_lifetime>30</history_failure_lifetime> <use_separate_process>1</use_separate_process> </group> </config>
あとは先程定義したcrontab.xmlのgroupタグのid属性を変えておきます。
これで独自のCronグループが定義でき、ジョブを他の処理から分割できました。
Cronジョブの罠
現時点のMagento2系安定版では、同じCronジョブが複数同時に実行されるという現象が報告されています。
将来的には解決される見通しになっていますが、ミッションクリティカルな処理でCronジョブを使用する場合は、排他制御などに十分注意する必要があるでしょう。