プレビュー生成のデファード対応:preview_status_url によるポーリングオプション
Lexxy はプレビュー可能な PDF や動画のアップロード後、プレビュー画像の URL を <img> に埋め込み、キャッシュバスター付きでポーリングし続けていました。この変更は、プレビュー生成が遅延するバックエンドでも軽量に状態確認できる preview_status_url オプションを導入し、従来のポーリング方式を置き換えます。
背景
Lexxy の従来実装では、サーバーがプレースホルダー画像を返す前提でプレビュー URL を繰り返し取得し、画像サイズがヒューリスティックな閾値を超えるまでキャッシュバスター付きリクエストを送っていました。結果として、プレビューが生成中でもリクエストスレッド上で画像生成が走り、負荷が跳ね返ってくるケースがありました。
この設計は、Active Storage が「リクエスト時にプレビューを生成」するデフォルト動作と合致しませんでした。バックエンドが遅延生成(バックグラウンドジョブ等)を行う場合、毎回のポーリングが実際の生成処理をトリガーしてしまい、エディタ側の UX が不必要に重くなります。
そこで、アップロードレスポンスに preview_status_url を任意で含めることで、プレビューの生成状態を軽量に監視できる新しいパスを設けました。このオプションはオプトイン方式であるため、既存のホストは変更不要で従来通り動作します。
技術的な変更
ActionTextAttachmentNode に対して次の定数と属性が追加されました:INITIAL_PREVIEW_POLL_DELAY_MS, MAX_PREVIEW_POLL_DELAY_MS, MAX_PREVIEW_POLL_ATTEMPTS、そして previewStatusUrl プロパティです。これにより、ノードはステータス URL の有無で二分岐し、ポーリングまたは画像プリロードを選択します。
@@
- constructor({ tagName, sgid, src, previewSrc, previewable, pendingPreview, altText, caption, contentType, fileName, fileSize, width, height, uploadError }, key) {
+ constructor({ tagName, sgid, src, previewSrc, previewable, previewStatusUrl, pendingPreview, altText, caption, contentType, fileName, fileSize, width, height, uploadError }, key) {
@@
- previewable: this.previewable,
+ previewable: this.previewable,
+ previewStatusUrl: this.previewStatusUrl,
さらに #pollForPreview メソッドが拡張され、this.previewStatusUrl が存在すれば #waitForPreviewByPollingStatus を呼び、無ければ #waitForPreviewByPreloadingImage を呼び出すロジックが実装されました。ステータスエンドポイントへのポーリングは 2xx が処理中、それ以外が完了とみなすシンプルな契約に基づき、指数バックオフと最大 20 回のリトライを行います。
テストスイートも同様に拡張され、preview_status_url.test.js で両パスが網羅的に検証されています。モックレイヤー active_storage_mock.js は includePreviewStatusUrl と previewStatusInitiallyProcessing フラグを受け取り、ステータス URL およびプレビュー URL のリクエスト記録を可能にしています。
設計判断
preview_status_url は任意フィールドとしてレスポンスに追加された点が重要です。ホスト側がバックグラウンドでプレビューを生成できる場合にだけこのエンドポイントを提供し、Lexxy は自動的に低負荷なステータスチェックへ切り替えます。逆にフィールドが無い場合は、従来通りプレビュー URL の直接ロードを行うため、既存の Active Storage 互換性がそのまま保たれます。
このオプトイン方式は、後方互換性 を最大化しつつ新機能を導入できる典型的な設計パターンです。コード上の変更は主にノードのコンストラクタとポーリングロジックの追加に留まり、既存 API(previewable や src など)への影響はありません。また、バージョン番号とドキュメントの更新(docs/attachments.md)だけで機能が利用可能になるため、デプロイリスクが低減します。
まとめ
この PR は、プレビュー生成が遅延する環境でもエディタ側の負荷を抑える preview_status_url オプションを導入し、既存のポーリングロジックを置き換えました。オプトイン方式により従来の動作はそのまま維持され、バックエンドが余計なリクエストでプレビュー生成を起動することが防止されます。結果として、Lexxy はよりスケーラブルでバックエンド多様性に対応したプレビュー機構を提供します。