2026/06/19

エージェントと実行対象③ - UnprocessedDocuments の特徴と注意点

前回は、UnprocessedDocuments と UpdateProcessedDoc を紹介しました。

UnprocessedDocuments でエージェントがまだ処理していない文書の取得、UpdateProcessedDoc で処理済みフラグを設定し、次の実行では対象外にできるという使い方でした。処理すべき文書を効率的に取得できる機能なのですが、その陰に Notes/Domino アプリ開発的に意識すべき重要な点が 3 つあります。

  • ”未読/既読”に対する影響
  • 最終更新日の変化
  • エージェントの仕様変更時の影響


フィールドで管理

アプリ開発において、処理したかを記録するためには、フラグやステータスフィールドで管理するのが一般的です。例えば、次のようにプログラムです。

   Dim ns As New NotesSession
   Dim ndb As NotesDatabase
   Dim nv As NotesView
   Dim ndc As NotesDocumentCollection

   Set ndb = ns.CurrentDatabase
   Set nv = ndb.GetView("ByIsProcessed")   '処理済みフラグでソートされたビュー
   Set ndc = nv.GetAllDocumentsByKey("0", True)   '未処理を検索

   '未処理文書を順に処理
   Dim nd As NotesDocument
   Set nd = ndc.GetFirstDocument()

   While Not(nd Is Nothing)
      '(処理をここに記述)

      nd.IsProcessed = "1"   '処理済みフラグをセット
      Call nd.Save(True, True)   'フラグを保存

      Set nd = ndc.GetNextDocument(nd)   '次の文書を取得
   Wend

処理済みフラグ IsProcessed が "0" が未処理で、"1" が処理済みを表し、ビューで "0" の文書を検索して、ヒットした文書を順に処理をするという仕組みです。

ポイントは、Save メソッドをコールしている点です。文書が更新されるので、その文書が未読となってしまいます。


ちなみに、Save メソッドには引数が 3 つあって、最後の引数で未読をコントロールする機能があります。

ただ、ヘルプにも記載がある通り、この引数でコントロールできるのは処理を実行しているユーザだけです。その他ユーザに対してはすべて未読になるので、今回のような要件では効果がありません。


掲示板のように未読情報が重要なアプリでは、システム上の処理で未読になってしまっては、仕様上問題となります。例えば、削除日の1週間前に削除を通知する機能を作ったとしましょう。エージェントで送信済みフラグを書き込むと、未読になります。削除前なのに突然未読になり、逆に目立ってしまうということになってしまいます。

また、保存するということは、最終更新日が変化します。ビューで最終更新日順に表示しているビューではトップに表示されます。また、10 年更新がない文書は削除する機能があった場合、また 10 年間保持されることになります...。

文書が更新されということは、複製の対象になり、すべての複製先のサーバに反映される点にも注意が必要ですね。


UnprocessedDocuments の注意点

UnprocessedDocuments、UpdateProcessedDoc を使った処理済みフラグの管理では、文書を更新しません。よって、先の「フィールドで管理」で挙げた未読/既読情報や最終更新日は変化しません。

だからといって、この方法が全能で優れているわけではなく、使用時には注意があります。

それは、エージェントを更新するとリセットされるということです。そのため、機能変更などによりエージェントを修正すると、次回実行時には修正前に処理した文書も含めて実行対象となります。

14.5.1 を使って検証したところ、エージェントのコードに変更がなければ処理済みフラグはリセットされないようです。例えば、エージェントを開き再保存したり、「すべての LotusScript をリコンパイル」しただけではクリアされませんでした。ただ、機能は一切変えず、コメントを追記しただけでもフラグはクリアされてしまいました。内部的にどのように管理しているのでしょうね ??

機能強化はもちろん、バグ修正、リファクタリングなどを行う時の制限となりうるのです。「作成または変更されたすべての文書」を使って効率的に文書を取得しているのに、エージェントの最終更新日と比較するのもなんだか変ですよね...


ただ、この問題には回避策があります。

それは、エージェント内のコードをすべてスクリプトライブラリに外だしすることです。例えば、エージェントで行う処理の中身を UnprocessedDocsMain 関数に記述し、lsUnprocessedDocs ライブラリの中に記述します。

そしてエージェントでは、次のようにライブラリの関数を呼ぶだけにします。

Option Declare
Use "lsUnprocessedDocs"

Sub Initialize
   Call UnprocessedDocsMain() 'エージェントの本体
End Sub

将来仕様が変わっても更新するのは、lsUnprocessedDocs ライブラリとなるので、エージェントは更新されません。これにより処理済みフラグを維持することができます。


また、この処理済みフラグはエージェントごとに保持される仕組みなのですが、各文書に対して、どのエージェントで処理済みなのか確認するすべがありません。フィールドを利用したフラグ管理の場合には、文書のプロパティや確認用のビューを作成するなど、効率的に調査ができます。


このように UnprocessedDocuments の利用では、開発終了後、運用フェーズになってからの注意点が多いことに注意しましょう。


まとめ

処理済みフラグの管理方法には 2 種類あることを紹介しました。改めてそれぞれの特徴を整理しましょう。

UnprocessedDocuments フィールドで管理
文書の更新 なし あり(最終更新日が変化)
未読/既読 変化なし 未読になる
調査/確認 対象文書を確認できない 文書のプロパティやビューなどで確認可能
処理時刻 不明
別途処理ログを出力するなどすれば確認可能
最終更新日やフィールドに記録することで確認できる

これまでの経験でいうと、障害や問い合わせ対応は想定外な場合が多いです。その際により詳細に情報収集できる、フィールドで管理する方法の方法が安心だといえます。文書を更新しても構わない(未読/既読にあまりこだわらない)場合は、ステータスを文書に保存する方法をおススメします。

UnprocessedDocuments を使った処理済みフラグの管理は、文書を更新できないというような条件がある場合にとどめたほうが良いと思います。

どちらの方法も、メリット/デメリットがありますので、特徴を理解したうえで使い分けましょう。


0 件のコメント:

コメントを投稿