FessのS3・GCS一覧が空のとき、接続失敗と区別するための修正案

Fessのストレージ画面でファイルが見つからないとき、バケットが空なのか、認証や接続に失敗しているのかは区別したいところです。S3・GCSストレージプラグインでは、一覧取得中の例外を捕まえて空または途中までの一覧を返す経路がありました。そのため、取得失敗が正常な「0件」に見えることがあります。

この動作を改善するS3側のPR #4とGCS側のPR #6が提案されています。2026年10月17日の確認時点では両方とも未マージです。以下は修正案の説明であり、Fess 15.9.0や公開済みプラグインに反映済みという案内ではありません。

一覧取得の失敗を呼び出し元へ伝える

修正案では、listObjects内で発生した例外をStorageExceptionとして呼び出し元へ伝えます。メッセージには対象のバケットとprefixが入り、元の例外も原因として保持します。GCSでは一覧ページの取得だけでなく、結果を走査している途中の失敗も対象です。

Fess 15.9.0側の管理処理には、例外を受けてストレージアクセスエラーにする経路があります。プラグイン側で例外を握りつぶさなければ、管理画面・管理APIで正常な空一覧と区別できるようになります。

ただし、すべてのエラーが新しい動作になるわけではありません。S3のNoSuchBucketExceptionは従来どおりINFOログを記録し、空の一覧を返す扱いが残ります。GCSの修正案は、存在しないバケット等の取得例外もエラーとして伝えます。S3とGCSで「バケットがない」場合の動作は揃っていません。

空の一覧が返る場合に確認すること

この修正で新しい有効化設定は追加されません。利用には、対象のストレージ種類に合うプラグイン、バケット、認証情報、接続先の設定が必要です。修正を試す場合は、対応PRを含むプラグインを検証環境へ導入し、Fess本体との互換性も確認してください。未マージの修正が既存環境へ自動適用されることはありません。

既存環境で一覧が空なら、まず次を確認します。

  • ストレージ種類とプラグインが一致しているか。プラグインを導入・変更した場合はFessを再起動したか。
  • エンドポイント、バケット名、リージョンまたはプロジェクト、認証情報が対象環境に合っているか。
  • 実行環境から接続先へ到達でき、オブジェクト一覧を取得する権限があるか。
  • 指定したprefixが正しいか。サブディレクトリ相当のprefixを指定していれば、別の場所にあるオブジェクトは表示されない。

Fess側でプラグインが見つからない、認証情報が未設定といった初期化エラーを表示できても、その後のプラグイン内部の一覧取得失敗まで常に表示できるとは限りません。修正前の環境では「0件、成功」という応答だけで接続正常と判断しないようにします。

件数制限やダウンロードの問題とは分けて考える

正常に取得できた空バケットは、修正後も空の一覧です。また、Fess 15.9.0のstorage.max.items.in.pageの初期値は1000で、このPRは上限やページングを変更しません。画面に見える一覧だけでバケット内の全オブジェクト数を判断することはできません。

対象はオブジェクト一覧の失敗通知です。ダウンロード、アップロード、削除の動作や、接続可否を調べる別のメソッドを一括で変える修正ではありません。自動再試行や認証情報の修復も追加されません。

導入を検討する際は、正常な空バケット、オブジェクトのあるprefix、接続先へ到達できない状態をそれぞれ確認すると、0件と失敗を区別できるかを確かめやすくなります。S3の存在しないバケットの例外扱いも、運用監視の条件に含めてください。

関連PR

Fessの実験的なBacklog連携で課題を検索し、権限と削除を管理する

Backlogの課題、コメント、Wiki、ドキュメント、添付・共有ファイルをFessから検索するための実験的なデータストアが用意されています。今回のPRでは、実験的な提供であることと設定上の注意が明記され、HTTP 429後の待機を最低1秒にする改善がマージされました。

Fess本体15.9.0は正式公開済みですが、fess-ds-backlogは実環境での検証を広げている段階です。特にドキュメント・共有ファイルのURLや一部の添付取得には実スペースで未検証の項目があり、事前検証を前提として導入します。

プラグインと専用アカウントを準備する

Fess 15.9に対応するプラグインJARを管理画面の「システム」→「プラグイン」でローカルファイルとして導入するか、app/WEB-INF/plugin/へ配置して再起動します。データストア設定のハンドラーでBacklogDataStoreを選びます。

Backlogにはクロール専用ユーザーを用意し、対象プロジェクトへ参加させてAPIキーを発行します。管理者でも未参加プロジェクトをすべて取得する設定ではありません。閲覧のみ等の制限ロールでは添付や共有ファイルが403となり、該当機能がスキップされる場合があります。

Fessのパラメーターは、まず小さな1プロジェクトに限定して設定します。

api_key=REPLACE_WITH_BACKLOG_API_KEY
space_url=https://example.backlog.com
project_keys=EXAMPLE
script_type=javascript

space_urlはHTTPSのスキームとホストを指定します。対応するホストは*.backlog.com、*.backlog.jp、*.backlogtool.comです。APIキーは専用ヘッダーで送信され、リダイレクトは追跡しません。Javaのorg.codelibs.curlロガーをFINEへ上げると専用ヘッダーが記録される可能性があるため、診断時も注意してください。

スクリプトには次を設定します。権限同期には最後の行が必要です。

title=backlog.title
content=backlog.content
url=backlog.url
mimetype=backlog.mimetype
created=backlog.created
last_modified=backlog.updated
role=backlog.roles

データストアのスクリプト種類が未設定だとGroovyになります。Groovyは15.9本体に同梱されないため、この例ではscript_type=javascriptを明示しています。

初期値と所要時間を確認する

パラメーター初期値
project_keys空(APIユーザーが参照できる全プロジェクト)
include_archivedfalse
include_issues / include_comments / include_wikistrue
include_documents / include_attachments / include_shared_filestrue
permission_synctrue
default_permissions空
max_file_size10485760バイト
request_interval200ミリ秒
search_request_interval1000ミリ秒
max_retry_count5

毎回全件クロールします。課題ごとにコメント取得があるため、10万件なら200ミリ秒の待機だけでも約5.5時間かかり、実際には一覧・添付取得等の時間が加わります。レート制限はAPIキー単位ではなくユーザー単位で共有されるため、同じユーザーの別処理も考慮します。

429ではX-RateLimit-Resetに従って1〜120秒待機し、ヘッダーがなければ60秒待機します。今回の修正は、サーバー時刻との差等でリセット時刻が過去になっても再試行を即座に使い切らないためのものです。

プロジェクト権限を検索へ反映する

permission_sync=trueでは、プロジェクトメンバーのメールアドレスとユーザーIDから{user}権限を作ります。Fessのログイン名がBacklogの識別子に対応していることが前提です。別人が同じログイン名を持つ環境では、そのまま対応付けてはいけません。

Fess管理画面の「アクセス権限」に初期入力される{role}guestは削除してください。これを残すと同期した権限へ追加され、匿名検索を含む全員が検索できる構成になります。role=backlog.rolesも忘れず設定します。

検索権限はプロジェクト単位です。Backlogで添付をダウンロードできない閲覧専用メンバーでも、Fess側では同プロジェクトの取得済み添付を検索できる場合があります。元サービスの機能別権限まで再現するものではありません。メンバー取得に失敗したプロジェクトは権限なしで登録せず、スキップして失敗URLへ記録します。

削除とメンバー変更は即時反映とは限らない

標準では文書に有効期限が付き、初期値3日で期限切れ後に削除されます。元データを削除した場合やメンバーが脱退した場合も、古い権限の文書が約3日残る可能性があります。権限を含む文書IDが変わるため、残ったメンバーには重複結果が見える場合もあります。

クロール終了時に未再登録文書を削除したい場合は、次を検討します。

keep_expires_docs=false

ただし、途中の403、一覧取得失敗、プロジェクトのスキップ、中断でも到達できなかった既存文書が削除対象になります。即時削除を優先するか、一時障害中も結果を保持するかを決めて設定してください。

失敗項目があってもジョブ全体は成功する場合があります。「クローラー」→「失敗URL」とfess-crawler.log、利用者ごとの検索結果、結果リンクの遷移を確認します。未知の共有ファイル種別は警告を出してスキップします。まず課題・Wikiなどの小さな範囲で、権限と更新・削除の動作まで検証するのがよいでしょう。

関連PR

FessのデータクロールでJavaScriptの日付を登録する

データストアのスクリプトでnew Date(...)を返すと、日付ではなくJavaScriptのオブジェクトとして登録され、日付フィールドの型エラーになる場合がありました。FessのJavaScriptエンジンで、評価結果の日付をjava.util.Dateへ変換する修正がマージされました。

最終更新日時のフィールド名

インデックスのフィールド名はlast_modifiedです。lastModifiedという別の名前では、最終更新日時を設定できません。

JavaScriptで実行するデータストア設定のスクリプト欄で、timestampという変数にエポック秒が入っている例です。変数名は利用しているデータストアが公開する名前に合わせてください。

last_modified=new java.util.Date(Number(timestamp) * 1000)

java.util.DateはすでにJavaの日付なので、この修正による変換は不要です。修正を含むビルドでは、次の組み込みDateを返す書き方もJavaの日付へ変換されます。

last_modified=new Date(Number(timestamp) * 1000)

15.9開発版ではJavaScriptが既定のスクリプトエンジンです。ただしデータストア設定で選択するエンジンを確認してください。Groovyなどの別エンジンへ同じ例をそのまま適用する説明ではありません。秒をミリ秒へ変換するために1000倍しており、元データがミリ秒なら掛け算は不要です。

変換の範囲と制限

変更の対象はJavaScriptエンジンの評価結果そのものがDateである場合です。オブジェクトや配列の内側にあるDateを再帰的に変換する処理は追加していません。無効なDateはエポック時刻ではなくnullになります。文字列などDate以外の結果はそのままです。

修正前の型エラーでは、その文書を含む一括登録が失敗することがあります。失敗したデータは自動的に復元されるわけではないため、スクリプトを直して対象を再クロールし、障害URLやクロールログ、実際のlast_modifiedを確認してください。PRでは変換処理の単体テストを実施していますが、実CSVクロールによる検証は未実施とされています。

関連PR