ServiceNow開発者の皆さん、スクリプトの処理タイミングを意図的に少し遅らせたい時に gs.sleep() を使おうとしていませんか? 簡単に処理を一時停止できるメソッドですが、特にBusiness Rule(ビジネスルール)内で不適切に使用すると、システム全体のパフォーマンスに致命的な悪影響を与える可能性があります。ここでは、gs.sleep()のリスクと、実用的なコード例を交えた推奨の代替手段を解説します。
Business Ruleでのgs.sleep()の危険性
- システムスレッドのブロック:
gs.sleep()はバックグラウンドのワーカースレッド(システムの処理枠)を解放せず、「スリープ状態のまま拘束」してしまいます - 同期処理での使用は厳禁:
BeforeやAfterのような同期処理で使用すると、ユーザーの画面読み込みがフリーズします。複数人が同時に実行するとインスタンス全体が重くなる原因(ノードのリソース枯渇)に繋がります
推奨される代替手段
処理を遅らせる場合は、システムリソースを直接ブロックしない以下の方法を選択してください。
- 非同期(Async)ビジネスルールの活用: 即時の応答が必要ない重い処理は、実行タイミングを
Asyncに設定する - Flow Designerの待機機能: 時間経過を待つ場合は
Wait for a duration of timeアクションを使用する - スケジュール済みイベントへの委譲:
gs.eventQueueScheduled()を使い、指定時刻にバックグラウンドでシステムに処理させる
実装コード例(アンチパターンと推奨策)
以下は、処理を「10秒遅らせたい」場合の対比例です。
❌ アンチパターン(避けるべき悪い例)
// 同期のBusiness Ruleでワーカースレッドを10秒間、強制的にブロックしてしまう
// ユーザーはその間、画面のローディングが止まらず待たされます
gs.sleep(10000);
// ここから本来やりたい処理...✅ ベストプラクティス(Sys Eventを使った非同期処理)
// 1. GlideDateTimeで現在時刻から「10秒後」の時間を計算
var when = new GlideDateTime();
when.addSeconds(10);
// 2. スレッドをブロックせず、10秒後に 'my.delayed.event' を非同期で発火させる予約をする
// ※ 受け取り側の処理は事前にスクリプトアクション(Script Action)等で定義しておきます
gs.eventQueueScheduled('my.delayed.event', current, gs.getUserID(), gs.getUserName(), when);まとめ
- ユーザーを待たせる同期処理のBusiness Rule内で
gs.sleep()を使用することは絶対に避けてください - 処理の実行を意図的に遅らせたい場合は イベントのスケジュール実行 や Flow Designer といった非同期の仕組みを活用するのが鉄則です
- スレッドを無駄にブロックしない、システムに優しいスクリプト設計を心がけましょう
一言まとめ: 👉 gs.sleep() でシステムを止めるのではなく、gs.eventQueueScheduled() などの非同期処理を賢く活用しよう!