PleasanterでGroupIdを取得できずユーザー連携が停止|役職欄の「主席」を調べた事例

ワンポイント画像

Pleasanterのユーザー・グループ情報を更新する定期ジョブが、人事情報の変更後に正常終了しなくなりました。処理内容を追うと、Pleasanterのグループを設定するために必要なGroupIdを正常に取得できていませんでした。さらに対象ユーザーの元データまで戻って確認したところ、本来はシステムで定義されたコードを想定していた役職項目に、「主席」という文字列が設定されていました。今回の原因はPleasanterそのものの障害ではなく、連携処理が前提としていたデータ形式と、実際に渡ってきた値の違いでした。

人事情報からPleasanterの所属グループを自動更新していた

今回の環境では、Pleasanterのユーザー情報を管理者がすべて手作業で管理していたわけではありません。所属や役職などの人事情報を利用し、定期ジョブでユーザーやグループの情報を更新していました。

この方法であれば、人事異動があるたびに管理者がPleasanterを開き、対象者一人ずつの所属を変更する必要がありません。通常時は非常に便利ですが、自動化された処理には「この項目にはこういう値が入る」という前提があります。

今回の場合、役職に関係する項目には、処理側で認識できるコード値が入ることを想定していました。普段はその前提で問題なく動いていたため、人事情報変更後にジョブが停止するまで、入力値の形式を疑うことはありませんでした。

自動連携では、プログラムが変わっていなくても元データの内容が変われば動作しなくなります。今回の調査は、その典型的なケースでした。

ジョブ全体ではなく、特定ユーザーを処理したところで問題が起きた

最初に確認したのはジョブの実行結果です。すべての利用者で処理できていないのであれば、Pleasanterへの接続や認証、ジョブ実行環境などを疑う必要があります。しかし今回は、途中までは処理が進んでいました。

そこで、正常に処理されたユーザーと、問題が発生したユーザーの境目を確認し、対象を絞り込みました。そのユーザーについて、所属情報、役職情報、Pleasanter側で設定しようとしているグループを順番に追っていきました。

調査を進めると、グループ設定時に必要となるGroupIdを求められていないことが分かりました。つまり、Pleasanterへデータを書き込む処理より前の、「この利用者をどのグループへ所属させるか」という判定部分で止まっていたことになります。

大量データを処理するジョブでは、プログラム全体を最初から読むより、「どのレコードまでは成功し、どのレコードから失敗したのか」を確認する方が早く原因へ近づける場合があります。

元データまで戻ると、役職項目に「主席」が入っていた

GroupIdを決定する処理がどのデータを参照しているのか確認した結果、役職に関係する項目へ「主席」という文字列が設定されていました。

既存処理は、役職情報として定義済みのコード値が渡されることを前提としていました。そのコードを条件にして、Pleasanter上のどのグループへ所属させるかを判定しています。ところが「主席」は既存のコードとして認識できない値だったため、対応するグループを判断できず、結果としてGroupIdを取得できませんでした。

ここで重要なのは、「主席」という名称そのものが悪いわけではないことです。問題は、コードを受け取る前提の項目へ、処理側が想定していない形式の値が入ったことです。

例えばコード「10」「20」「30」を想定している処理に「主席」という文字列が来れば、どれに対応するのかプログラム側では判断できません。人が見れば意味のある役職名でも、変換ルールがなければシステムでは扱えません。

役職情報を修正し、ジョブを再実行した

原因を特定した後、対象となる役職情報を処理側が扱える形へ修正し、ジョブを再実行しました。GroupIdが正常に取得され、Pleasanterのユーザー・グループ情報も更新されることを確認しています。

ここで注意したいのは、値を一時的に直すだけでは足りない場合があることです。正データを管理している上流システム側を直さなければ、次回の連携で同じ値が再び流れてきます。どこを正として、どの項目を修正するのか。障害対応では、復旧そのものと同じくらいこの判断が重要になります。

ほかの利用者にも「主席」がないか確認する必要があった

一人の利用者で想定外の値が見つかった場合、対象者だけを修正して終わりにすると、次の利用者で同じ問題が発生する可能性があります。そのため、同じ形式の値がほかの利用者にも存在しないか確認することが重要です。

確認の方法としては、役職項目の値と件数を一覧化するのが分かりやすいです。例えばデータベースで確認できる環境なら、次のような考え方で値の種類を洗い出せます。

SELECT RoleValue, COUNT(*) AS UserCount
FROM UserSource
GROUP BY RoleValue
ORDER BY RoleValue;

実際のテーブル名や項目名は環境に合わせる必要がありますが、「どんな値が何件存在するか」を一度一覧にすることで、想定外の文字列や未定義コードを見つけやすくなります。

GroupIdを取得する前に入力値を検証した方が原因が分かりやすい

今回の処理では、最終的にGroupIdを取得できないところで問題が表面化しました。しかし、再発防止を考えるなら、その手前で役職値を検証する方が分かりやすくなります。

例えば、役職コードとして許可している値の一覧を持ち、それ以外を受信した場合は、グループ検索へ進む前に未定義値として記録します。そのとき「対象ユーザー」「項目名」「受信値」「未定義であること」がログへ出れば、今回の「主席」のようなケースはすぐ判断できます。

また、1件の未定義値でジョブ全体を止めるのか、そのユーザーだけをエラー扱いにしてほかのユーザーを継続するのかも検討できます。重要な権限情報を扱うのであれば停止させる方が安全な場合もあり、逆に大量ユーザーの同期では一人だけ隔離して処理を続ける方が運用しやすい場合もあります。

どちらを選ぶとしても、想定外データが来る可能性を前提にしておくことで、障害発生時の調査負担を減らせます。

人事連携では「コードしか来ない」という前提を信用しすぎない

今回の事象で一番大きかった学びは、外部から受け取るデータ形式を固定的に考えすぎないことでした。役職以外でも、数値を想定している項目へ文字列が入る、マスタにないコードが来る、NULLになる、桁数が変わるといったことは起こり得ます。

特に人事情報は、制度変更、役職追加、組織改正などによって内容が変わりやすいデータです。ジョブを作った時点では正しかった前提が、数年後も正しいとは限りません。

自動化では「正常に動いているときの手間を減らす」だけでなく、「止まったときに誰でも原因を追える状態を作る」ところまで含めて設計する必要があると感じました。

コメント

タイトルとURLをコピーしました