「Record is too big」エラーによる Algolia 投稿再インデックスの中断の修正
Algolia にフォーラムの投稿のほんの一部しか含まれていないという問題に遭遇しました。投稿の再インデックスを実行したところ、原因が判明しました:
Algolia::AlgoliaHttpError:
Record at the position 258 objectID=1006 is too big:
size: 108426 byte(s), maximum allowed: 10000 byte(s).
私のインストール済みプラグインバージョンでは、PostIndexer#to_object が投稿全体のプレーンテキストを単一のレコードとして送信しており、シリアライズ後のレコードサイズを確認していません。サイズオーバーのレコードにより、再インデックスタスクが中断されました。
以下のローカルワークアラウンドにより、再インデックスを完了させることができました。
このパッチの内容
このパッチは、完全にシリアライズされた投稿レコードそれぞれを 9,500 バイトに制限し、Algolia から報告された 10,000 バイトの制限に対して余裕を持たせます。
パッチは以下を行います:
- メタデータと JSON エスケープをサイズ計算に含めます。
- Algolia に送信される
content 要素のみを切り詰めます。
- 元の Discourse 投稿は変更しません。
- 既存の object ID と「1 投稿につき 1 レコード」という構造を維持します。
トレードオフとして、長い投稿の末尾から省略されたテキストは Algolia 経由で検索できなくなります。これはドキュメントのチャンク分割ではなく、単なる切り詰め処理です。
パッチ
対象ファイル:
plugins/discourse-algolia/lib/discourse_algolia/post_indexer.rb
to_object の最後の return 文、任意のメタデータカテゴリが追加された直後を探します:
object
end
そのセクションを以下に置き換えます:
# 完全なシリアライズ済みレコードのサイズを制限する(コンテンツのみではなく)。
algolia_record_budget = 9_500
if object.to_json.bytesize > algolia_record_budget
full_content = object[:content]
object[:content] = ""
if object.to_json.bytesize > algolia_record_budget
raise "Algolia metadata alone exceeds the record budget for post #{post.id}"
end
low = 0
high = full_content.length
best_content = ""
while low <= high
midpoint = (low + high) / 2
object[:content] = full_content[0, midpoint]
if object.to_json.bytesize <= algolia_record_budget
best_content = object[:content]
low = midpoint + 1
else
high = midpoint - 1
end
end
object[:content] = best_content
end
object
end
二分探索により、JSON シリアライズ後にバイト予算に収まるコンテンツプレフィックスが見つかります。メタデータだけで予算を超えている場合、このパッチはメタデータをサイレントに破棄するのではなく、明示的なエラーを発生させます。
編集前にファイルのバックアップを作成してください。このパッチは、to_object が content を含む単一のハッシュを返すバージョンを対象としています。適用前にインストール済みのバージョンに対して確認してください。
検証と再インデックス
標準的な Docker インストールの場合、ホストからコンテナに入ります:
cd /var/discourse
./launcher enter app
Discourse ユーザーに切り替えます:
su - discourse
discourse ユーザーのプロンプトが表示されたら、以下を実行します:
cd /var/www/discourse
ruby -c plugins/discourse-algolia/lib/discourse_algolia/post_indexer.rb
Syntax OK と表示されたら、以下を実行します:
RAILS_ENV=production LOAD_PLUGINS=1 bundle exec rails algolia:reindex_posts
このタスクは投稿インデックスをクリアして再作成します。私の場合は、パッチ適用後に正常に完了しました。
継続的なインデックス処理でパッチ済みコードを使用するには、既に実行中のアプリケーション/バックグラウンドワーカープロセスの再起動も必要です。
別の落とし穴:報告される投稿数
タスクは以下を報告しました:
Successfully pushed 723 posts to Algolia
But Algolia contained 272 records.
しかし Algolia には 272 件のレコードしかありませんでした。
私のインストール済みバージョンでは、タスクはインデクサーの可視性フィルターを呼び出す前にカウンターを増加させます。同じインデクサーを使用した診断により、以下が確認されました:
Posts examined: 723
Eligible for indexing: 272
Excluded by visibility: 451
したがって、成功メッセージはアップロードされたレコード数ではなく、検証された投稿数をカウントしています。この不整合は、サイズオーバーのレコードエラーとは別の問題でした。