メインコンテンツへスキップ
見出し画像

イベントはキューに積まれてから動く(sysevent)


    ServiceNow で「あるレコードが更新されたら裏で別の処理が走る」「通知が飛ぶ」といった挙動の多くは、イベント(event)という仕組みを経由しています。イベントは発火したらすぐ実行されるのではなく、いったん キュー(sysevent)に積まれ、後からまとめて処理されます。そして「そのイベントが来たら何をするか」を定義するのが Script Action(sysevent_script_action)であり、「そもそもどんなイベント名が存在するか」を登録するのが Event Registry(sysevent_register)です。

    この記事では、イベントをプロセス論ではなく、実際の 3 つのテーブルを起点に追います。発火したイベントが積まれるキュー sysevent、登録済みイベント名の定義 sysevent_register、イベントで動くスクリプト sysevent_script_action を順に確認し、1 つのイベント発火が複数の処理を呼ぶ(ファンアウトする)様子まで、実機の件数で押さえます。

    この記事は、ServiceNow の Incident は触ったことがあるが、「イベント」や「Script Action」がどのテーブルを通って動くのかをこれから理解したい人を想定しています。管理者・開発者が実機で「イベントで動くはずの処理が動かない」を切り分けるとき、どのテーブルのどの項目を見るかを扱います。

    この記事で分かること

    • イベントが「発火 → キュー(sysevent)→ 処理 → state=processed」と進む流れ

    • イベント機構を支える 3 テーブル(キュー / 登録簿 / Script Action)の役割分担

    • Script Action(sysevent_script_action)が「どのイベントで・何を実行するか」をどの項目で持つか

    • 1 つのイベント名に複数の Script Action が紐づく(ファンアウトする)こと

    • sysevent.state(ready / processed / error / transferred)の意味と実機の内訳

    • 「イベントで動くはずの処理が動かない」を、どのテーブルのどの項目で切り分けるか

    この記事の内容は ServiceNow の PDI(Personal Developer Instance)Zurich(ズーリッヒ)リリースの OOTB(初期設定)で確認した個人メモです。本番環境やカスタマイズ済み環境では、登録イベント・Script Action・件数・state の内訳が異なる場合があります。イベントワーカー(スケジューラ)の実スケジューリングや同期実行の内部挙動には踏み込みません。


    ServiceNow のイベント(event)とは

    イベントは「何かが起きた」という合図を一度キューに積み、後から購読者(Script Action や通知)が拾って動く仕組みです。レコードの更新や定期処理などをきっかけに「incident.commented が起きた」といった名前付きの合図をキューに積み、それを待ち受けている処理を後から起動します。サーバサイドでは gs.eventQueue('incident.commented', current, ...) のような呼び出しでイベントを積みます(公式の概要は Event registry を参照)。

    ポイントは、イベントは発火と同時に処理されるわけではないことです。発火したイベントはまず キュー(sysevent)に行として積まれ、イベントワーカーが後からまとめて処理します。だから「イベントで動くはずの処理が動かない」ときも、①そもそも積まれたか、②名前は合っているか、③ハンドラ(Script Action)は有効か、④処理されたか、を段階で切り分けられます。


    イベントが処理されるまでの流れ

    まず全体像です。今回確認した PDI(Zurich / OOTB)では、イベントは次の流れで動く構成でした。


    画像
    • ① 発火 … gs.eventQueue(...) や OOTB の処理が、イベント名(例 incident.commented)を投げる。

    • ② キュー … sysevent に 1 行が積まれ、state=ready(処理待ち)になる。

    • ③ 処理 … イベントワーカーがキューを順に処理する。処理の内部スケジューリングは本記事の範囲外です。

    • ④ ハンドラ起動 … event_name が一致する Script Action や Notification が動く。

    • ⑤ 完了 … 処理が終わると sysevent の state=processed になる。

    つまり「イベントの発火」と「実際の処理」は別の段階です。sysevent はあくまで合図の置き場で、実際に何をするかは Script Action 側に書かれている、と捉えると切り分けやすくなります。

    実際のキューは、次のURLで確認できます(先頭の <YourInstance> は自分のインスタンスに置き換えてください)。

    https://<YourInstance>/sysevent_list.do?sysparm_query=ORDERBYDESCsys_created_on


    画像

    イベント機構を支える 3 つのテーブル

    イベントは 1 テーブルでは完結しません。今回の PDI では、役割の違う 3 テーブルが連携していました。


    画像


    画像

    3 テーブルの役割分担

    • sysevent(Event) … 発火したイベントが積まれるキュー(実体)。super_class は空の独立テーブルで、固有フィールドは 24 でした。1 イベント発火=1 行です。

    • sysevent_register(Event Registration) … システムが扱えるイベント名の登録簿(定義)。super_class は sys_metadata(Application File)で、固有フィールドは 10。今回の PDI では 763 件登録されていました。

    • sysevent_script_action(Script Action) … イベントで動くサーバサイドスクリプト。super_class は sysrule(Rule)で、メール通知(sysevent_email_action)と同じ Rule 系として管理されます。固有フィールドは 6 でした。

    3 つの関係を一言でいうと、登録簿が「どんな名前のイベントがあるか」を決めます。キューに「実際に起きたイベント」が積まれ、Script Action が「その名前が来たら何をするか」を持つ、という分担です。


    Script Action(sysevent_script_action)の構成

    Script Action は「どのイベントで(event_name)・どんな条件で(condition_script)・何を実行するか(script)」の 3 点で読みます。Script Action は server-side の JavaScript をイベント発火時に実行する仕組みです。ビジネスルールと違いイベントだけが起点になります(公式の概要は Script actions を参照)。


    画像

    実機のフォームを見ると、Script Action の中身は次の項目で構成されていました。

    フォームで確認できる項目

    • event_name(Event name) … 待ち受けるイベント名。これがキューに積まれたイベントの name と一致したときに動きます。

    • script(Script) … イベント発火時に実行する server-side JavaScript(最大 8000 文字)。event.parm1 などでイベントが運んだパラメータを受け取れます。

    • condition_script(Condition script) … 実行するかどうかの条件スクリプト。

    • active(Active) … 有効/無効(既定 false)。

    • synchronous(Synchronous) … 同期実行かどうかの項目(既定 false)。なお同期実行の実挙動は本記事の検証範囲外です。

    Script Action はイベント経由でしか起動しません。だから「Script Action が動かない」ときは、まず対応するイベントがキューに積まれているかを確認するのが起点になります。

    Script Action の一覧は、次のURLで確認できます。

    https://<YourInstance>/sysevent_script_action_list.do?sysparm_query=active=true


    画像

    イベントキューの state(処理状態)

    イベントが「積まれたが処理されていない」のか「処理済み」なのかは、sysevent の state で分かります。今回の PDI では 4 つの値(sequence順)でした。


    画像
    • ready … 生成直後・処理待ち(既定値)。ここで止まっているなら、まだワーカーが処理していません。

    • processed … ワーカーが処理を終えた状態。今回のキュー(約 1 万件)のほとんどがこれでした。

    • error … 処理でエラーになった状態。

    • transferred … 他ノード等へ移送された状態。

    切り分けでは、state=ready のまま長く残っているなら処理側(ワーカー/キュー)、そもそも行が無いなら発火側(イベントが積まれていない)を疑う、と分かれます。実機では、定期発火する glide.heartbeat だけでキューの過半を占め(確認時点で約 6,400〜7,000 件)、キューが常に動いていることが分かりました。再確認のたびに件数が増えるのは、heartbeat が 1 分間隔で積まれ続けるためです。


    1 イベント → 複数 Script Action(ファンアウト)

    イベント機構の効きどころは、1 つのイベント発火が複数の処理を呼べることです。同じ event_name を待ち受ける Script Action が複数 active なら、1 回の発火で全部が動きます。


    画像

    今回の PDI では、plugin.upgraded というイベント名を待ち受ける active な Script Action が 32 件ありました。プラグインがアップグレードされて plugin.upgraded が 1 回積まれると、この 32 件が(条件に合えば)それぞれ動きます。

    さらに、Script Action だけがイベントの購読者ではありません。 イベント発火を待つ通知(event 型の Notification)も同じキューを見ており、今回の PDI では active で 211 件ありました。つまり 1 つのイベント名に対して、複数の Script Action と複数の通知が同時にぶら下がり得ます。

    この「複数がぶら下がる」性質は便利な一方で、1 つのイベントで想定より多くの処理が走る原因にもなります。だから挙動を追うときは、「そのイベント名を誰が待ち受けているか」を Script Action と通知の両方で確認します。


    「イベントで動かない」をどこで見るか

    読者の一番の疑問は「イベントで動くはずの処理が動かないのはどこを見ればいいか」です。これまでのテーブルを使うと、次のように段階で切り分けられます。


    画像

    切り分けの 4 ステップ

    • ① 発火したか … sysevent に、そのイベント名の行があるか。無ければ発火していない(gs.eventQueue が呼ばれていない/条件に達していない)。

    • ② 名前が一致するか … キューの name と、Script Action / 登録簿の event_name が完全一致しているか。スペルやサフィックス違いで一致しないと動きません。

    • ③ ハンドラが有効か … 対応する Script Action が active か、condition_script で弾かれていないか。

    • ④ 処理されたか … sysevent.state を見る。ready のままなら処理側、error なら処理中の失敗です。

    切り分けの軸は、「合図(sysevent)」と「ハンドラ(sysevent_script_action)」を分けて見ることです。行があるのにハンドラが動かないのか、そもそも行が無いのかで、見るべきテーブルが変わります。


    イベント機構まわりのテーブル件数

    参考として、イベント機構に関わる主要テーブルの件数を載せます。今回確認した PDI(Zurich / OOTB・active中心・2026-06-21確認)の値です。


    画像

    OOTB の時点で「イベントの登録簿」も「ハンドラ」も大量に存在します。 今回の PDI では、イベント名の登録簿(sysevent_register)が 763 件(うち table を指定しているものは 573 件)でした。Script Action は 368 件(うち active 352)です。自分で作らなくても多くのイベントとハンドラが初期から動いています。どんなイベントが扱えるか・どう登録するかは、公式の手順 Register an event でも確認できます。

    イベント登録簿は、次のURLで確認できます。

    https://<YourInstance>/sysevent_register_list.do?sysparm_query=ORDERBYevent_name


    画像

    ServiceNow のイベント機構のポイント

    • イベントは発火と同時に実行されず、いったんキュー(sysevent)に積まれて後から処理されます。問題の切り分けは「積まれたか/処理されたか」を state で見ます。

    • イベント機構は 3 テーブルの分担です。sysevent(キュー・実体)/ sysevent_register(イベント名の登録簿・定義)/ sysevent_script_action(イベントで動くスクリプト)。Script Action は通知と同じ Rule(sysrule)系です。

    • Script Action は「event_name・condition_script・script」で読み、イベント経由でしか起動しません。動かないときは対応イベントがキューにあるかが起点です。

    • sysevent.state は ready / processed / error / transferred の 4 値。ready のまま残るなら処理側、行が無いなら発火側を疑います。

    • 1 つのイベント名に複数の Script Action や通知がぶら下がれます(今回 plugin.upgraded に active 32 件)。便利な反面、想定外に多くの処理が走る原因にもなります。

    イベントを調べるときは、まず「合図(sysevent)を見るのか、ハンドラ(sysevent_script_action)を見るのか」を切り替えます。そのうえで①発火→②名前一致→③ハンドラ有効→④state、の順で確認するのが近道です。


    次に読むなら

    次に調べるなら、gs.eventQueue の第3・第4引数(parm1 / parm2)でイベントに渡すパラメータの設計、custom queue(第5引数)による処理の分離、condition_script でハンドラを絞り込む書き方、そして event 型の Notification(sysevent_email_action)とイベントの結びつきです。通知側からイベントを追う流れは、姉妹記事「Email Notification を実機で確認する」で扱っています。イベントワーカー(スケジューラ)の実スケジューリングや同期実行の内部挙動は、本記事で「範囲外」とした部分にあたります。


    実機で気づいたこと

    登録簿(sysevent_register)の763件のうち、tableを指定しているレコードは573件でした。残り約190件はtableを指定せず登録されています。最初は「登録簿=テーブルごとのイベント定義」だと思っていましたが、ログインやハートビートのようにレコードに紐づかないイベントは、tableが空のまま登録簿に載ることが分かりました。

    もう一つの気づきは、登録簿が持つフィールドです。名前とテーブルだけの単純な台帳だと思っていましたが、実機のフォームにはpriority・queue・fired_by・suffix・caller_accessまで並んでいました。登録簿はイベント名を定義するだけでなく、そのイベントをどの優先度・どのキューで扱うかまで、あらかじめ決めておける構造になっています。特定のイベントだけ処理が遅いと感じたときは、sysevent側のstateだけでなく、登録簿側のpriorityやqueueも見る価値がありそうです。

    super_class の違いも実務的だと感じました。sysevent_register は sys_metadata(Application File)配下です。sysevent_script_action は sysrule(Rule)配下です。つまりイベント名は、通知やUI Actionと同じ「メタデータ定義」として扱われています。一方でScript Actionは、Business Ruleやメール通知と同じ「実行されるルール」として分類されています。定義と実行を、管理上も分けている設計だと読み取れました。

    Script Action の active 率も気になりました。368件中activeは352件で、全体の約96%です。残り16件がなぜ無効のままなのかは分かりませんが、棚卸しをするなら、この非active分が何のために作られたのかを確認する価値がありそうです。

    用語

    • PDI:Personal Developer Instance(無料の検証用インスタンス)

    • OOTB:Out of the Box(初期設定のまま)

    • イベント:sysevent テーブルに積まれる「何かが起きた」という名前付きの合図

    • イベントキュー:sysevent テーブル(発火したイベントが行として積まれる置き場)

    • Event Registry:sysevent_register テーブル(扱えるイベント名の登録簿)

    • Script Action:sysevent_script_action テーブル(イベントで動くサーバスクリプト)

    • gs.eventQueue:サーバサイドでイベントをキューに積む GlideSystem の API

    自分の環境で確認するときのURL

    自分のインスタンス名を先頭に付けると、同じ画面が開けます。

    イベントキュー        : sysevent_list.do?sysparm_query=ORDERBYDESCsys_created_on
    イベント登録簿        : sysevent_register_list.do?sysparm_query=ORDERBYevent_name
    Script Action(active) : sysevent_script_action_list.do?sysparm_query=active=true
    キューの state 別      : sysevent_list.do?sysparm_query=GROUPBYstate
    キューのフィールド     : sys_dictionary_list.do?sysparm_query=name=sysevent^elementISNOTEMPTY

    検証範囲とおことわり

    • 確認した範囲:sysevent / sysevent_register / sysevent_script_action の super_class(テーブルの位置づけ)、固有フィールド数(24 / 10 / 6)、sysevent.state の 4 値(sequence順)と実機の件数内訳、各テーブル件数、plugin.upgraded を待ち受ける active な Script Action の件数(32)、event 型 Notification の件数(211)、代表的な OOTB のイベント名・登録・Script Action。すべて PDI(Zurich / 2026-06-21 確認)の OOTB で取得しています。

    • 確認していない範囲:イベントワーカー(スケジューラ)の実スケジューリングと処理タイミング、synchronous=true の実挙動、process_on / queue / partition による優先処理の内部仕様、各 Script Action の script の中身、custom queue(gs.eventQueue 第5引数)の実動作。これらは別記事で扱います。

    今回は PDI の OOTB(初期設定)を前提に、イベントが発火してから Script Action が動くまでのテーブル構造を確認しました。実環境では、既存のカスタマイズによってイベント登録・Script Action・件数が変わります。

     
     
    ServiceNowのPDI(Personal Developer Instance)を実機で観察して、Noteに記事を書いています 実装・運用・教育の現場視点で淡々と記録中です リクエストがあればその記事も書きます 個人の観察日記です

    あなたへのおすすめ