これは InterSystems FAQ サイトの記事です。
「定期的にプロセスを監視し、あるイベントが発生したときにのみ処理を実行したい」ような場合に使用できる、便利な機能をご紹介します。
もちろん、Forループを行う常駐プロセスを作成してその中で Hang XX しながらIf文にてイベントを検知したり、タスクスケジュールでルーチンを定期実行してその中でIf文にてイベントを検知して処理することも可能です。
今回ご紹介する、%SYSTEM.Event クラスを使用することで、よりシンプルに処理を作成することが可能となります。
【こんな時に便利】
・テーブルやグローバルに、あるデータが全て格納されたら処理を行いたい
・あるエラーを検知したときにのみ、^SystemCheck情報を取得したい
・処理が必要なものがデータベースに入ったら順番に処理を行いたい(pythonだとQueueモジュールのような感じ)
【使用方法】
準備(任意のプロセス)
do $SYSTEM.Event.Create("test")
これで、testというイベントがシステムワイドで作成されます。
パターンA=単純な常駐プロセス
(1) 待機プロセス側
do $SYSTEM.Event.Wait("test")
このコマンドの瞬間、このプロセスは待ち状態になります。
(2) 起こす側
do $SYSTEM.Event.Signal("test")
これで、指定イベントで待機しているプロセスの待ち状態が解除されます。
パターンB=メッセージ付き常駐プロセス
(1) 待機プロセス側
set msg=$SYSTEM.Event.WaitMsg("test")
このコマンドの瞬間、このプロセスはウェイクアップイベントを待機しながらスリープ状態に入ります。
、他プロセスからのメッセージを待ちます。
(2) 起こす側
do $SYSTEM.Event.Signal("test",msg)
指定イベントで待機しているプロセスにメッセージ(msg)を送り待ち状態を解除します。
リクエストを処理する常駐プロセスにて、SYSTEM.Event.Wait() または$SYSTEM.Event.WaitMsg() でリクエストを待ちます。
リクエストを行うプロセスは、$SYSTEM.Event.Signal() で常駐プロセスに通知します。
以下は、パターンAでリクエストを処理する常駐プロセスのサンプルです。
10秒(timeout)ごとに監視し、$SYSTEM.Event.Signal() があれば、^SystemCheck 情報を収集します。
^Zevent("STOP") グローバルがセットされたら、監視を終了します。
set timeout=10
set requestnum=0
set status=$SYSTEM.Event.Create("test")
while '$g(^Zevent("STOP")) {
set st=$SYSTEM.Event.Wait("test",timeout)
if st=1 {
set Status =$$INT^SystemCheck()
write "Request done",!
}
if st=0 write "Timeout",!
}
Quit
※sample.macで %SYSネームスペースに保存するとします
【実行例】
端末A 常駐プロセス
%SYS>do ^sample
端末B リクエストプロセス
%SYS>do $SYSTEM.Event.Signal("test")
※例えば、messages.logファイルを読み込み、「○○エラー」のような該当するエラーメッセージがあればこのコマンドを実行します。
このコマンドを実行することで、^SystemCheck情報が収集されます。
停止
%SYS>set ^Zevent("STOP")=1
※<IRISインストールディレクトリ>\mgr 以下に
<CustomerName>yyyy….html // ^SystemCheck情報
のファイルが出力されているようであれば、情報収集を行ったことになります。
set ^Zevent("STOP")=1 を実行して、常駐プロセスを終了します。
このコマンドを実行しない限り、常駐プロセスは繰り返し監視をし続けます。
以下は、パターンBでリクエストを処理する常駐プロセスのサンプルです。
set timeout=10
set requestnum=0
set status=$SYSTEM.Event.Create("test")
while '$g(^Zevent("STOP")) {
set msg=$SYSTEM.Event.WaitMsg("test",timeout)
if $li(msg,1)=1 set ^Zevent("REQUEST",$i(requestnum),$ZDT($H))=$li(msg,2) write "Request done",!
if $li(msg,1)=0 write "Timeout",!
}
Quit
※sample2.macで WORKネームスペースに保存した場合
【実行例2】
端末A 常駐プロセス
WORK>Do ^sample2
端末B、端末C リクエストプロセス
WORK>do $SYSTEM.Event.Signal("test","Request From "_$J_" "_$ZDT($H))
※複数のプロセスが通知した場合、通知はキューイングされる仕組みとなっています。
常駐プロセスは、通知を受けると待ちが解除されるので、その後処理を行い、また待ちに入る処理を行います。
停止
WORK>set ^Zevent("STOP")=1
結果例
WORK>zw ^Zevent
^Zevent("REQUEST",1,"08/13/2021 11:35:13")="Request From 16584 08/13/2021 11:34:31"
^Zevent("REQUEST",2,"08/13/2021 11:35:13")="Request From 16584 08/13/2021 11:34:41"
^Zevent("REQUEST",3,"08/13/2021 11:35:13")="Request From 22296 08/13/2021 11:34:54"
^Zevent("REQUEST",4,"08/13/2021 11:35:13")="Request From 22296 08/13/2021 11:34:56"
^Zevent("REQUEST",5,"08/13/2021 11:35:13")="Request From 16584 08/13/2021 11:34:59"
^Zevent("REQUEST",6,"08/13/2021 11:35:13")="Request From 22296 08/13/2021 11:35:02"
^Zevent("REQUEST",7,"08/13/2021 11:35:13")="Request From 16584 08/13/2021 11:35:07"
^Zevent("REQUEST",8,"08/13/2021 11:35:13")="Request From 22296 08/13/2021 11:35:09"
^Zevent("STOP")=1
【ご参考】
Simple $system.Event examples(英語)