[CentOS6][SOS JobScheduler] 複雑なジョブの組み合わせをイベントで制御する


Create: 2014/09/22
LastUpdate: 2014/09/22
[ メニューに戻る ]

Jobscheduler FAQの「Start of JobChains by Events, Configurations for EventHandler in data file」 では、複雑なジョブの組み合わせをイベントで制御します。動作確認してみたかったのですが、サンプルコードが提供されていないようなので、自分で作ってみました。
ちなみに、JobScheduerFAQ には JOE での作成手順が記載されています。(JOEの画面はドイツ語ですが。。)
動作確認は、JobScheduler1.7 を使用しています。

シナリオ


下図のような流れで、7つの帳票(JobRep10-JobRep70)を作成するジョブを考えます。


JobScheduler への実装方法


Job10系(10-11-12-13)とJob20系(20-21-22-23) を以下のようなJobChainにして、個別に実行することにします。
  • JobChain10: Job10、Job11、Job12、Job13
  • JobChain20: Job20、Job21、Job22、Job23
後続のジョブは、イベント制御で自動的に実行するようにします。
下図はイベントフローです。後述するイベント制御ファイルを作成するときの設計図になります。
イベント名は、"ev_<イベントを作成したジョブ>_<イベントを受信するジョブ>" とします。
ボックスの右端にあるイベント名は、そのジョブが生成します。OKは正常時、NOKは異常時、指定がない場合はジョブ起動時に生成することにします。
ボックスの左側にあるイベント名は、そのジョブの起動条件です。記載されたイベントが全部そろったらジョブを実行します。


今回作成したファイルは、以下のとおり。
debug.pl については、「 [CentOS6][SOS JobScheduler] 複数のJobChain 並列に実行し、複数の同期ポイントを設定する」を参照してください。
$ tree ./live/sample2
├── EventAdd.job.xml ・・・・・・・ イベント生成
├── Job10.job.xml ・・・・・・・・  テストジョブ
├── Job11.job.xml ・・・・・・・・  テストジョブ
├── Job12.job.xml ・・・・・・・・  テストジョブ
├── Job13.job.xml ・・・・・・・・  テストジョブ
├── Job20.job.xml ・・・・・・・・  テストジョブ
├── Job21.job.xml ・・・・・・・・  テストジョブ
├── Job22.job.xml ・・・・・・・・  テストジョブ
├── Job23.job.xml ・・・・・・・・  テストジョブ
├── Job31.job.xml ・・・・・・・・  テストジョブ
├── Job32.job.xml ・・・・・・・・  テストジョブ
├── Job33.job.xml ・・・・・・・・  テストジョブ
├── Job41.job.xml ・・・・・・・・  テストジョブ
├── Job42.job.xml ・・・・・・・・  テストジョブ
├── Job43.job.xml ・・・・・・・・  テストジョブ
├── JobChain10.config.xml ・・・・・ JobChain10用の設定ファイル
├── JobChain10.job_chain.xml ・・・ JobChain10
├── JobChain20.config.xml ・・・・・ JobChain20用の設定ファイル
├── JobChain20.job_chain.xml ・・・ JobChain20
├── JobChain31.config.xml ・・・・・ JobChain31用の設定ファイル
├── JobChain31.job_chain.xml ・・・ JobChain31
├── JobChain32.config.xml ・・・・・ JobChain32用の設定ファイル
├── JobChain32.job_chain.xml ・・・ JobChain32
├── JobChain33.config.xml ・・・・・ JobChain33用の設定ファイル
├── JobChain33.job_chain.xml ・・・ JobChain33
├── JobChain41.config.xml ・・・・・ JobChain41用の設定ファイル
├── JobChain41.job_chain.xml ・・・ JobChain41
├── JobChain42.job_chain.xml ・・・ JobChain42
├── JobChain43.config.xml ・・・・・ JobChain43用の設定ファイル
├── JobChain43.job_chain.xml ・・・ JobChain43
├── JobChainRep10.job_chain.xml ・・ JobChainRep10
├── JobChainRep20.job_chain.xml ・・ JobChainRep20
├── JobChainRep30.job_chain.xml ・・ JobChainRep30
├── JobChainRep40.job_chain.xml ・・ JobChainRep40
├── JobChainRep50.job_chain.xml ・・ JobChainRep50
├── JobChainRep60.job_chain.xml ・・ JobChainRep60
├── JobChainRep70.job_chain.xml ・・ JobChainRep70
├── JobRep10.job.xml ・・・・・・・ テストジョブ(帳票)
├── JobRep20.job.xml ・・・・・・・ テストジョブ(帳票)
├── JobRep30.job.xml ・・・・・・・ テストジョブ(帳票)
├── JobRep40.job.xml ・・・・・・・ テストジョブ(帳票)
├── JobRep50.job.xml ・・・・・・・ テストジョブ(帳票)
├── JobRep60.job.xml ・・・・・・・ テストジョブ(帳票)
├── JobRep70.job.xml ・・・・・・・ テストジョブ(帳票)
└── debug.pl ・・・・・・・・・・・ デバッグファイル出力用

$ tree ./events/
└── Sample2Events.actions.xml・・・  イベント制御ファイル

JobChain10、JobChain20


JobChain10、JobChain20の内容は以下のとおり。(JobCain20は数字を読み替え)
JobChainでは、JobChainSplitterでジョブを並列実行し、ジョブが終了したら EventAddジョブでイベントを生成します。
<?xml version="1.0" encoding="ISO-8859-1"?>
<job_chain title="JobChain10">
    <job_chain_node  state="StartJobChain10" job="/sos/jitl/JobChainStart" next_state="Job10" error_state="!error"/>
    <job_chain_node  state="Job10" job="Job10" next_state="SplitJobChain10" error_state="!error"/>
    <job_chain_node  state="SplitJobChain10" job="/sos/jitl/JobChainSplitter" next_state="EndJobChain10" error_state="!error"/>
    <job_chain_node  state="SplitJobChain10:Job11" job="Job11" next_state="SetEventOK_11" error_state="!error"/>
    <job_chain_node  state="SetEventOK_11" job="EventAdd" next_state="EndJobChain10" error_state="!error"/>
    <job_chain_node  state="SplitJobChain10:Job12" job="Job12" next_state="SetEventOK_12" error_state="!error"/>
    <job_chain_node  state="SetEventOK_12" job="EventAdd" next_state="EndJobChain10" error_state="!error"/>
    <job_chain_node  state="SplitJobChain10:Job13" job="Job13" next_state="SetEventOK_13" error_state="SetEventNOK_13"/>
    <job_chain_node  state="SetEventOK_13" job="EventAdd" next_state="EndJobChain10" error_state="!error"/>
    <job_chain_node  state="SetEventNOK_13" job="EventAdd" next_state="!error" error_state="!error"/>
    <job_chain_node  state="EndJobChain10" job="/sos/jitl/JobChainEnd" next_state="finish" error_state="!error"/>
    <job_chain_node  state="finish"/>
    <job_chain_node  state="!error"/>
</job_chain>
設定ファイルでは、JobChainSplitter で並列実行するジョブと、EventAddで生成するイベントをパラメータに設定します。
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="scheduler_configuration_documentation.xsl"?>
<settings>
    <job_chain name="JobChain10">
        <order>
            <params/>
            <process state="SplitJobChain10">
                <params>
                    <param name="state_names" value="SplitJobChain10:Job11;SplitJobChain10:Job12;SplitJobChain10:Job13"/>
                </params>
            </process>
            <process state="SetEventOK_11">
                <params>
                  <param name="scheduler_event_add" value="add"/>
                  <param name="scheduler_event_class" value="Report"/>
                  <param name="scheduler_event_id" value="ev_Job11_JobRep60;ev_Job11_JobRep10;ev_Job11_Job31"/>
                </params>
            </process>
            <process state="SetEventOK_12">
                <params>
                  <param name="scheduler_event_add" value="add"/>
                  <param name="scheduler_event_class" value="Report"/>
                  <param name="scheduler_event_id" value="ev_Job12_JobRep10;ev_Job12_Job32"/>
                </params>
            </process>
            <process state="SetEventOK_13">
                <params>
                  <param name="scheduler_event_add" value="add"/>
                  <param name="scheduler_event_class" value="Report"/>
                  <param name="scheduler_event_id" value="ev_Job13_JobRep10;ev_Job13_Job33;ev_Job13_JobRep50"/>
                </params>
            </process>
            <process state="SetEventNOK_13">
                <params>
                  <param name="scheduler_event_add" value="add"/>
                  <param name="scheduler_event_class" value="Report"/>
                  <param name="scheduler_event_id" value="ev_Job13_Job33"/>
                </params>
            </process>
        </order>
    </job_chain>
</settings>

JobChian31 - JobChain41


JobChain31からJobChain41の内容は以下のとおり。(各JobChainで数字は読み替え)
ジョブを実行後、EventAdd でイベントを生成しますが、JobChain42 だけは、イベント制御ファイルでイベントを生成するので、EventAdd はありません。
<?xml version="1.0" encoding="ISO-8859-1"?>
<job_chain title="JobChain31">
    <job_chain_node  state="StartJobChain31" job="/sos/jitl/JobChainStart" next_state="Job31" error_state="!error"/>
    <job_chain_node  state="Job31" job="Job31" next_state="SetEventOK_31" error_state="SetEventNOK_31"/>
    <job_chain_node  state="SetEventOK_31" job="EventAdd" next_state="EndJobChain31" error_state="!error"/>
    <job_chain_node  state="SetEventNOK_31" job="EventAdd" next_state="!error" error_state="!error"/>
    <job_chain_node  state="EndJobChain31" job="/sos/jitl/JobChainEnd" next_state="finish" error_state="!error"/>
    <job_chain_node  state="finish"/>
    <job_chain_node  state="!error"/>
</job_chain>

設定ファイルでは、EventAddで生成するイベントをパラメータに設定します。
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="scheduler_configuration_documentation.xsl"?>
<settings>
    <job_chain name="JobChain31">
        <order>
            <params/>
            <process state="SetEventOK_31">
                <params>
                  <param name="scheduler_event_add" value="add"/>
                  <param name="scheduler_event_class" value="Report"/>
                  <param name="scheduler_event_id" value="ev_Job31_Job41;ev_Job31_JobRep60;ev_Job31_JobRep30"/>
                </params>
            </process>
            <process state="SetEventNOK_31">
                <params>
                  <param name="scheduler_event_add" value="add"/>
                  <param name="scheduler_event_class" value="Report"/>
                  <param name="scheduler_event_id" value="ev_Job31_Job41"/>
                </params>
            </process>
        </order>
    </job_chain>
</settings>

JobChainRep10-JobChainRep70


JobChainRep10からJobChainRep70の内容は以下のとおり。(各JobChainで数字は読み替え)
イベント生成は、イベント制御ファイルで実施します。
<?xml version="1.0" encoding="ISO-8859-1"?>
<job_chain title="JobChainRep10">
    <job_chain_node  state="StartJobChainRep10" job="/sos/jitl/JobChainStart" next_state="JobRep10" error_state="!error"/>
    <job_chain_node  state="JobRep10" job="JobRep10" next_state="EndJobChainRep10" error_state="!error"/>
    <job_chain_node  state="EndJobChainRep10" job="/sos/jitl/JobChainEnd" next_state="finish" error_state="!error"/>
    <job_chain_node  state="finish"/>
    <job_chain_node  state="!error"/>
</job_chain>

設定ファイルはありません。

テストジョブ(Job10-Job41、JobRep10-JobRep70)


ジョブの内容は以下のとおり。全部同じです。
<?xml version="1.0" encoding="ISO-8859-1"?>
<job order="yes">
    <script  language="shell">
        <![CDATA[
echo "$SCHEDULER_JOB_NAME processed $SCHEDULER_ORDER_ID"
echo "Current Timestamp: `date '+%Y-%m-%d %H:%M:%S'`"
echo "Current Hostname: `uname -n`"
echo "Current Username: `whoami`"
exit 0
        ]]>
    </script>
    <monitor name="process0" ordering="0">
        <script language="perl">
          <include file="./config/live/sample2/debug.pl"/>
        </script>
    </monitor>
    <run_time />
</job>

イベント生成ジョブ(EventAdd)


ジョブの内容は以下のとおり。並列実行できるように tasks を 10 にしています。
<?xml version="1.0" encoding="ISO-8859-1"?>
<job order="yes" tasks="10">
    <params/>
    <script language="java" java_class="sos.scheduler.job.JobSchedulerSubmitEventJob"/>
    <monitor name="configuration_monitor" ordering="0">
        <script java_class="sos.scheduler.managed.configuration.ConfigurationOrderMonitor" language="java"/>
    </monitor>
    <monitor name="process0" ordering="0">
        <script language="perl">
          <include file="./config/live/sample2/debug.pl"/>
        </script>
    </monitor>
    <run_time />
</job>

イベント制御ファイル


イベント制御ファイルは、<JobScheduler_base>/config/events ディレクトリに作成します。
ファイル名には命名規則がありますが、今回は、Sample2Events.actions.xml にします。
内容は、以下のとおり。
<action>が図2のボックス1つになります。<events>に起動条件、<commands>に起動条件が成立したときに実行するコマンドを設定します。
<?xml version="1.0" encoding="UTF-8"?>
<actions>
  <action name="JobChain31">
    <events logic="and">
      <event_group group="Report" logic="and" event_class="Report">
        <event event_id="ev_Job11_Job31" event_title="Job11 OK" />
        <event event_id="ev_Job21_Job31" event_title="Job21 OK" />
      </event_group>
    </events>
    <commands>
      <command name="cmdJobChain31" scheduler_host="localhost" scheduler_port="4444">
        <add_order job_chain="sample2/JobChain31" id="JobChain31" replace="yes" />
      </command>
      <remove_event>
        <event event_id="ev_Job11_Job31" event_class="Report" />
      </remove_event>
      <remove_event>
        <event event_id="ev_Job21_Job31" event_class="Report" />
      </remove_event>
    </commands>
  </action>

~省略~

  <action name="JobChain42">
    <events logic="and">
      <event_group group="Report" logic="and" event_class="Report">
        <event event_id="ev_Job32_Job42" event_title="Job32 OK" />
      </event_group>
    </events>
    <commands>
      <command name="cmdJobChain42" scheduler_host="localhost" scheduler_port="4444">
        <add_order job_chain="sample2/JobChain42" id="JobChain42" replace="yes" />
      </command>
      <remove_event>
        <event event_id="ev_Job32_Job42" event_class="Report" />
      </remove_event>
      <add_event>
        <event event_id="ev_Job42_JobRep40" event_class="Report" />
      </add_event>
    </commands>
  </action>

~省略~

  <action name="JobChainRep70">
    <events logic="and">
      <event_group group="Report" logic="and" event_class="Report">
        <event event_id="ev_JobRep10_JobRep70" event_title="JobRep10 OK" />
        <event event_id="ev_JobRep20_JobRep70" event_title="JobRep20 OK" />
        <event event_id="ev_JobRep30_JobRep70" event_title="JobRep30 OK" />
        <event event_id="ev_JobRep40_JobRep70" event_title="JobRep40 OK" />
      </event_group>
    </events>
    <commands>
      <command name="cmdJobChainRep70" scheduler_host="localhost" scheduler_port="4444">
        <add_order job_chain="sample2/JobChainRep70" id="JobChainRep70" replace="yes" />
      </command>
      <remove_event>
        <event event_id="ev_JobRep10_JobRep70" event_class="Report" />
      </remove_event>
      <remove_event>
        <event event_id="ev_JobRep20_JobRep70" event_class="Report" />
      </remove_event>
      <remove_event>
        <event event_id="ev_JobRep30_JobRep70" event_class="Report" />
      </remove_event>
      <remove_event>
        <event event_id="ev_JobRep40_JobRep70" event_class="Report" />
      </remove_event>
    </commands>
  </action>
</actions>

動作確認


最初に上記設定をJOC、JIDで確認します。
各JobChainは、JOCで、下図のように見えます。


イベント制御ファイルは、定義した action が JIDの[Event Handler]タブで、下図のように見えます。


まず、JOCで、JobChain10 を実行します。
下図は、実行中の状態です。


JobChain10 の実行終了後、debug.log でジョブの実行状況を見ると以下のとおり。
イベントの起動条件が成立したので、JobChainRep10 は自動的に実行されています。
2014-09-22 11:50:16 - START - JOB=sample2/Job10 - ORDER_ID=556
2014-09-22 11:50:16 - END   - JOB=sample2/Job10 - ORDER_ID=556
2014-09-22 11:50:21 - START - JOB=sample2/Job13 - ORDER_ID=556_SplitJobChain10:Job13
2014-09-22 11:50:21 - START - JOB=sample2/Job11 - ORDER_ID=556_SplitJobChain10:Job11
2014-09-22 11:50:21 - START - JOB=sample2/Job12 - ORDER_ID=556_SplitJobChain10:Job12
2014-09-22 11:50:21 - END   - JOB=sample2/Job12 - ORDER_ID=556_SplitJobChain10:Job12
2014-09-22 11:50:21 - END   - JOB=sample2/Job11 - ORDER_ID=556_SplitJobChain10:Job11
2014-09-22 11:50:21 - END   - JOB=sample2/Job13 - ORDER_ID=556_SplitJobChain10:Job13
2014-09-22 11:50:25 - START - JOB=sample2/EventAdd - ORDER_ID=556_SplitJobChain10:Job11
2014-09-22 11:50:25 - START - JOB=sample2/EventAdd - ORDER_ID=556_SplitJobChain10:Job13
2014-09-22 11:50:25 - START - JOB=sample2/EventAdd - ORDER_ID=556_SplitJobChain10:Job12
2014-09-22 11:50:31 - END   - JOB=sample2/EventAdd - ORDER_ID=none
2014-09-22 11:50:31 - END   - JOB=sample2/EventAdd - ORDER_ID=none
2014-09-22 11:50:31 - END   - JOB=sample2/EventAdd - ORDER_ID=none
2014-09-22 11:50:34 - START - JOB=sample2/JobRep10 - ORDER_ID=JobChainRep10
2014-09-22 11:50:34 - END   - JOB=sample2/JobRep10 - ORDER_ID=JobChainRep10

この時点でのイベントの状況は、JID で確認できます。
JIDの[Event Handler]タブでは、各アクションごとのイベントの状況(ステータス、生成時間、有効期限)を確認できます。
下図の例では、JobChain10 がイベントの"ev_Job12_Job32" を生成したので、[EventStatus]欄が "active" になっています。後1つのイベントが生成されたら、JobChain32 は自動的に実行されます。


JIDの[Events]タブでは、現在、存在しているイベントの一覧を確認できます。
[Job]、[Job Chain]欄が空白なのは、イベント制御ファイルで生成を定義したイベントです。


最後に、JobChain20 を実行します。これで、残りのジョブは全部実行されます。
下図は実行中の画面です。


debug.log は以下のとおり。残りのジョブが全部実行されています。
2014-09-22 12:06:30 - START - JOB=sample2/Job20 - ORDER_ID=565
2014-09-22 12:06:30 - END   - JOB=sample2/Job20 - ORDER_ID=565
2014-09-22 12:06:35 - START - JOB=sample2/Job23 - ORDER_ID=565_SplitJobChain20:Job23
2014-09-22 12:06:35 - END   - JOB=sample2/Job23 - ORDER_ID=565_SplitJobChain20:Job23
2014-09-22 12:06:35 - START - JOB=sample2/Job12 - ORDER_ID=565_SplitJobChain20:Job22
2014-09-22 12:06:35 - START - JOB=sample2/Job21 - ORDER_ID=565_SplitJobChain20:Job21
2014-09-22 12:06:35 - END   - JOB=sample2/Job12 - ORDER_ID=565_SplitJobChain20:Job22
2014-09-22 12:06:35 - END   - JOB=sample2/Job21 - ORDER_ID=565_SplitJobChain20:Job21
2014-09-22 12:06:37 - START - JOB=sample2/EventAdd - ORDER_ID=565_SplitJobChain20:Job23
2014-09-22 12:06:38 - START - JOB=sample2/EventAdd - ORDER_ID=565_SplitJobChain20:Job22
2014-09-22 12:06:38 - START - JOB=sample2/EventAdd - ORDER_ID=565_SplitJobChain20:Job21
2014-09-22 12:06:44 - END   - JOB=sample2/EventAdd - ORDER_ID=none
2014-09-22 12:06:44 - END   - JOB=sample2/EventAdd - ORDER_ID=none
2014-09-22 12:06:44 - END   - JOB=sample2/EventAdd - ORDER_ID=none
2014-09-22 12:06:49 - START - JOB=sample2/Job33 - ORDER_ID=JobChain33
2014-09-22 12:06:49 - END   - JOB=sample2/Job33 - ORDER_ID=JobChain33
2014-09-22 12:06:51 - START - JOB=sample2/EventAdd - ORDER_ID=JobChain33
2014-09-22 12:06:52 - START - JOB=sample2/Job31 - ORDER_ID=JobChain31
2014-09-22 12:06:52 - END   - JOB=sample2/Job31 - ORDER_ID=JobChain31
2014-09-22 12:06:55 - START - JOB=sample2/EventAdd - ORDER_ID=JobChain31
2014-09-22 12:06:57 - START - JOB=sample2/Job32 - ORDER_ID=JobChain32
2014-09-22 12:06:57 - END   - JOB=sample2/Job32 - ORDER_ID=JobChain32
2014-09-22 12:06:57 - END   - JOB=sample2/EventAdd - ORDER_ID=none
2014-09-22 12:07:01 - START - JOB=sample2/Job43 - ORDER_ID=JobChain43
2014-09-22 12:07:01 - END   - JOB=sample2/Job43 - ORDER_ID=JobChain43
2014-09-22 12:07:04 - START - JOB=sample2/Job41 - ORDER_ID=JobChain41
2014-09-22 12:07:04 - END   - JOB=sample2/Job41 - ORDER_ID=JobChain41
2014-09-22 12:07:07 - START - JOB=sample2/JobRep30 - ORDER_ID=JobChainRep30
2014-09-22 12:07:07 - END   - JOB=sample2/JobRep30 - ORDER_ID=JobChainRep30
2014-09-22 12:07:09 - START - JOB=sample2/JobRep20 - ORDER_ID=JobChainRep20
2014-09-22 12:07:09 - END   - JOB=sample2/EventAdd - ORDER_ID=none
2014-09-22 12:07:09 - END   - JOB=sample2/JobRep20 - ORDER_ID=JobChainRep20
2014-09-22 12:07:12 - START - JOB=sample2/JobRep70 - ORDER_ID=JobChainRep70
2014-09-22 12:07:12 - END   - JOB=sample2/JobRep70 - ORDER_ID=JobChainRep70
2014-09-22 12:07:15 - START - JOB=sample2/JobRep50 - ORDER_ID=JobChainRep50
2014-09-22 12:07:15 - END   - JOB=sample2/JobRep50 - ORDER_ID=JobChainRep50
2014-09-22 12:07:17 - START - JOB=sample2/Job42 - ORDER_ID=JobChain42
2014-09-22 12:07:17 - END   - JOB=sample2/Job42 - ORDER_ID=JobChain42
2014-09-22 12:07:20 - START - JOB=sample2/JobRep60 - ORDER_ID=JobChainRep60
2014-09-22 12:07:20 - END   - JOB=sample2/JobRep60 - ORDER_ID=JobChainRep60
2014-09-22 12:07:22 - START - JOB=sample2/JobRep40 - ORDER_ID=JobChainRep40
2014-09-22 12:07:22 - END   - JOB=sample2/JobRep40 - ORDER_ID=JobChainRep40