記事
· 8 hr 前 4m read

監視用常駐プロセスを作成する方法

これは 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 {
        // timeout内に通知(Signal)があれば、 SystemCheck情報収集
        set Status =$$INT^SystemCheck() 
        write "Request done",!    // write 出力は debug 用(本番では消してOK)
     }
     if st=0 write "Timeout",!     // write 出力は debug 用
 }
 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


enlightened【ご参考】
Simple $system.Event examples(英語)

ディスカッション (0)0
続けるにはログインするか新規登録を行ってください