JavaScript
バッチ
schedule
ServiceNow

ServiceNowでデータ整理バッチ処理を作成する

概要

日々の業務によりトランザクションテーブルにデータを追加していったときに、保持期限が切れたら自動的に削除する仕組みをバッチ処理で作成する場合がある。
今回はServiceNowのScheduled script executionをこの仕組みを作成する。

仕様

整理対象のテーブルとデータの保持期限、データの保持期限を判定するための対象テーブルの列名を保持するテーブル「DataReductionSettings」テーブルを作成しておく。
Schedule script executionで作成された処理が起動すると、「DataReductionSettings」テーブルから整理対象のテーブル名、日付保持の列名、保持期間(日数)を取得する。
取得した情報を元に、GlideRecordのdeleteMultipleで条件に一致するレコードを一括削除する。

環境

ServiceNow:KINSGTONE

手順

DataReductionSettingsテーブルを作成

下記の項目を持つテーブルを作成する。
なお、Table NameはLabelから自動生成されるが、今回の私の環境では「x_211750_angular_a_datareductionsettings」になっている。
これは後でスクリプトで利用するので、各自の環境に合わせて変更が必要だ。

Column Name Type 解説
tablename String(Full UTF-8) 整理対象テーブル名
periodcolumnname String(Full UTF-8) 日付判定用の列名
period Integer 保持日数

Schedule script executionを作成

studiioのCreate Application FileでServer DevelopmentカテゴリーのSchedule script executionを選択してCreateをクリック。Nameや、実行間隔などは適当に設定する。またActiveのチェックは一旦はずして保存する。

データ整理バッチ.png

下記のスクリプトをRun this scriptに入力する。

// 整理対象設定テーブルからレコードを読み込む
var reductionSettingsRecord = new GlideRecord('x_211750_angular_a_datareductionsettings');  
reductionSettingsRecord.query();


while (reductionSettingsRecord.next()) {
    // 整理対象テーブル名
    var tableName = reductionSettingsRecord.getValue('tablename');
    // 整理対象日付判定用の列名
    var periodColumnName = reductionSettingsRecord.getValue('periodcolumnname');
    // 保持期限(日数)
    var period = reductionSettingsRecord.getValue('period');

    gs.info('target table = ' + tableName);
    gs.info('periodColumnName = ' + periodColumnName);
    gs.info('period = ' + period);

        // 整理対象日付を「本日日付 - 保持期限(日数)」で算出
    var expiredDate = new GlideDateTime();
    expiredDate.addDaysLocalTime(Number(period * -1));

    gs.info('expiredDate = ' + expiredDate.getLocalDate());

    var reductionRecord = new GlideRecord(tableName);
        // 整理対象テーブルを「判定用の列名 <= 整理対象日付」で抽出 
    reductionRecord.addQuery(periodColumnName, '<=', expiredDate);
    reductionRecord.query();
    // 処理対象件数をあらかじめ取得しておく
    var targetCount = reductionRecord.getRowCount();

    gs.info('targetCount = ' + targetCount);
    // 一括削除実行
    reductionRecord.deleteMultiple();

}

スクリプトの説明はスクリプトコメントに記載しているため割愛する。

実行

Activeのチェックは外しているので定期実行はされないが設定画面の「Execute Now」をクリックすれば即時実行される。

最後に

少しだけ迷った事がある。日付の演算処理で、GlideDateTimeにsubtract(減算)があったので、subtractDayみたいなのを探してしまったが無かった。
少し考えて「addDaysLocalTime」で引数に負数を渡せば良い事に気づいた。

また、少しはまったことがある。

日付の演算結果を代入しようと最初は下記のようなコードを書いてしまっていた。

var today = new GlideDateTime();
var expiredDate = today.addDaysLocalTime(Number(period * -1));

最近は、Javaでオブジェクトは基本的にイミュータブルで作る事に慣れているし、各種フレームワークなどもそのように設計されているものが多いため上記のコードを自然に書いてしまっていた。javascriptは基本的にミュータブルオブジェクトですね。

ちょっと困った事
deleteMultipleで処理対象となった件数を戻り値で返してくれない。
EffectCountのようなメソッドも無い。
今回は、実行直前に同じ検索条件で件数を取得しているが、これで良いのか他に良い書き方が無いのか探している。