自動投稿スクリプトが、別の自動処理が挿した画像を毎回消していた話

  • #自動化
  • #画像処理
  • #冪等性
  • #投稿パイプライン
自動投稿スクリプトが、別の自動処理が挿した画像を毎回消していた話

今回やったこと

下書きから本文を組み直す更新処理と、公開後に画像を差し込む処理の間で起きた衝突を整理する。対象は、本文を下書きから再生成する投稿スクリプトと、既存投稿へ挿絵を追加する画像処理レッグである。別々に見るとどちらも正しい処理でも、同じ投稿を異なる正本から更新すると、後から加えた情報が消える。

今回の記録で扱うのは、本文画像が消えた原因と、再発を抑えるために追加した引き継ぎ処理である。公開状態や投稿先の設定を変更する話ではなく、更新処理が既存データをどう扱うかという設計の話に絞る。

消えた理由は「画像処理の失敗」ではなかった

実際の問題は、既存投稿の更新で本文画像が2枚消えたことだった。画像を挿入する処理が画像を失ったのではない。画像挿入後に、別の更新処理が本文を下書きから作り直し、その結果で既存本文を上書きしたためである。復旧後に同じ更新を実行すると再び消えたので、単発の通信エラーではなく、処理の責務と正本の不一致だった。

下書きは記事の骨格を持っている。一方、公開後に差し込まれた本文画像は、下書きへ戻す処理を持っていない。そこで「下書きから作れば常に最新」という前提が、後段で付加されたデータを捨てる動作になっていた。

下書き本文 ──再構成──> 更新本文

公開後の本文画像 ────────┘ ここを知らないと画像が消える

重要なのは、どちらか一方を正しい処理として残すことではない。更新前に、別レッグが追加したデータを識別し、下書きから再構成した本文へ戻す必要がある。識別できないものまで機械的に残すと、古い広告や不要なHTMLまで引き継ぐ危険があるため、対象を限定する必要もある。

引き継ぎの対象を prompts.json で限定する

実装では、画像処理レッグが把握している非 featured 画像だけを引き継ぐようにした。対象画像と配置位置は prompts.json に記録されている。featured 画像は本文内の挿絵とは役割が異なるため、本文へ引き継がない。

見出しを配置の手掛かりにし、該当する見出しの直後へ画像を戻す。見出しが変更されていて位置を特定できない場合は、失わないことを優先して末尾へフォールバックする。この判断は、画像が消える不可逆な結果を避けつつ、誤った位置への自動配置を限定するためのものだ。

回帰テストでは、第一章と第二章に対応する2枚がそれぞれの見出し直後へ戻ること、2回目の更新で画像が増殖しないこと、featured 画像を本文へ入れないことを確認している。見出しが変わった場合の末尾フォールバック、挿絵が無い記事、prompts.json が無い記事、新規投稿も個別に扱う。

状態更新時の扱い
非 featured 画像が記録済み見出し位置を手掛かりに引き継ぐ
見出しが変わった末尾へフォールバックする
featured 画像本文へ引き継がない
挿絵の記録がない本文を変更しない
新規投稿引き継ぎ処理をしない

やってみてわかったこと

後段の処理が本文へ追加したものを、前段の再構成処理が知らないまま上書きすると、各処理の単体テストだけでは見つけにくい。必要なのは、投稿処理を通しで何度も実行しても結果が壊れないかを確認するテストである。特に「2回目は何も足さない」という冪等性は、画像・通知・外部APIなど、再実行される処理ほど先に定義しておきたい。

今回の修正では、すべての既存HTMLを無条件に保存するのではなく、画像処理側が記録した対象だけを扱った。この境界があることで、本文の正本を下書きに置いたまま、後段の付加情報だけを失わずに済む。複数の自動処理を組み合わせる場合は、「誰が本文を作るか」だけでなく、「誰が追加した情報を次の更新がどう認識するか」まで記録形式に含める必要がある。

更新履歴

  • 2026-08-31: 初稿。候補キューの記録とリポジトリ内の投稿・テスト実装をもとに整理。

参照

  • MT の投稿スクリプト(既存記事の更新時に図版を引き継ぐ側)
  • 同・図版引き継ぎの回帰テスト
  • PR #1605