← 一覧に戻る
chibabot-PWA 非同期プロキシ計画
2026年2月24日 Codex LGTM
📌 一言でいうと
メッセージを送った後、アプリを閉じても裏側で処理が続くようにする改修
🎯 なぜこれが必要なのか
iPhoneで chibabot PWA(ホーム画面に追加したWebアプリ)を使っていると、
メッセージを送った直後にアプリを閉じると返事が消えてしまう問題があったの。
これは「電話」に例えると分かりやすいわ。今のシステムは電話をかけて相手が喋り終わるまで待つ方式。
通話中に電話を切ったら、相手が何を言ったかは永遠に分からない。
chibabotの返答は複雑な質問だと2〜3分かかることもあるから、
その間ずっとアプリを開いているのは現実的じゃないわ。
iPhoneは節電のために、しばらく操作しないとアプリを「凍結」するから、
待っているだけでも接続が切れることがある。
過去に6回(v1〜v6)アプリ側だけで修正を試みたけど、全て失敗。
原因は通信の仕組みそのものにあるから、アプリ側をいくら直しても意味がなかったの。
Claude(私)と Codex(GPT-5.3)が独立して調査して、同じ結論に辿り着いたわ。
🏗️ 何をするのか
通信方式を「電話」から「留守電」に変える
❌ 今まで(電話方式)
- 送信→返事まで接続を維持
- アプリ閉じたら返事消滅
- 2〜3分間の接続維持が必須
- iPhoneの凍結で接続が切れる
✅ 改修後(留守電方式)
- 送信だけして即完了(0.2秒)
- 裏側で独立して処理が進む
- 結果は24時間保存される
- アプリを開けばいつでも取得
具体的な仕組み
↓
☁️
サーバーが「受け付けたよ」と即レスポンス
同時にAlarm(目覚まし時計)をセット
↓ この間、アプリを閉じてOK
⏰
Alarm が独立して起動 → chibabotに質問を送る
最大15分間処理できる(2〜3分の返答に余裕で対応)
失敗しても自動で最大6回リトライ
↓
💾
返答を保管庫(KV)に24時間保存
深夜に送って翌朝見てもOK
↓
📱
アプリを開くと保管庫をチェック → 即座に返答を表示
📊 技術的なステップ
1
サーバーの引っ越し
Cloudflare Pages(旧居)から Cloudflare Workers(新居)に移行。
Pages は Cloudflare がメンテナンスモード(新機能追加なし)にしていて、
今回必要な Durable Objects(長時間動くプログラム)が使えない。
Workers は Cloudflare が推奨している新しい方式よ。
2
Durable Objects + Alarm の設置
「Durable Objects」(DO)は、サーバー上で独立して動き続けるプログラムのこと。
普通のサーバー処理は数秒で終わらなきゃいけないけど、
DO の「Alarm」機能を使うと最大15分間独立して動ける。
しかも失敗したら自動的にやり直してくれるの(最大6回)。
3
KV(保管庫)の設置
KV(Key-Value ストア)は「名前をつけて物を保管する棚」のようなもの。
メッセージIDを名前にして、chibabotの返答を保管する。
24時間保持されるから、しばらく後にアプリを開いても結果が残ってるわ。
4
アプリ側の改修
アプリのメッセージ送信ロジックを「送って待つ」から「送って、定期的に結果を確認する」に変更。
確認間隔は最初3秒、徐々に伸ばして最大15秒に(指数バックオフ)。
アプリを閉じて再度開いた時も、まず保管庫を確認して結果があれば即表示。
5
デプロイ方法の変更
GitHub にコードを push した時の自動デプロイを Pages 用から Workers 用に切り替え。
設定ファイル1行の変更だけで移行完了。
🛡️ 安全装置
Codex(GPT-5.3)に3ラウンドレビューしてもらい、全ての穴を塞いだわ。
| 安全装置 | 何をするか |
| 冪等キー(べきとうキー) |
同じメッセージを2回送っても、chibabotへの問い合わせは1回だけ。二重課金なし |
| Alarm 自動リトライ |
サーバーエラー(5xx)やレート制限(429)は自動でやり直し。最大6回、間隔を空けて再試行 |
| トークンハッシュ認証 |
結果の取得時にトークンのハッシュ値(暗号化した指紋)で本人確認。他人が結果を盗み見れない |
| stale pending 検出 |
20分経っても処理中のままなら「詰まった」と判断して再送信。完全に詰まることがない |
📋 Codex レビュー経緯
OpenAI の Codex(GPT-5.3)に3回レビューしてもらった結果:
Round 1: 5つの重大な指摘 NOT LGTM
- DO の実行保証が不十分 → Alarm パターンに変更
- waitUntil が30秒で切れる → waitUntil 不使用に変更
- 二重実行の穴 → 冪等チェック強化
- 処理が詰まった時の回復手段なし → Alarm 自動リトライ + stale 検出
- 結果の取得が認証なし → トークンハッシュ追加
Round 2: 4つの追加指摘 NOT LGTM
- サーバーエラー(5xx)をリトライしていない → throw でリトライ
- Alarm の重複セットの可能性 → 常時セット + 冪等チェック
- 詰まり検出の閾値が短すぎ → 10分 → 20分に延長
- 認証がヘッダー存在チェックのみ → SHA-256 ハッシュ検証
Round 3: 全指摘解消 LGTM ✓
「4件とも設計意図どおり塞がっている」— Codex
💰 コスト
Cloudflare Workers 有料プラン: 月額 $5(約750円)
chibabot のサーバーが同じアカウントで動いているなら、既に有料プランのはず。追加コストなし。
✅ テスト方法
- PWA でメッセージを送信
- 返答の「...」が表示されている間にホーム画面に戻る
- 2分以上待つ
- アプリに戻る
- 1回目の復帰で返答が表示されれば成功 🎉
💡 ポイント
なぜ6回も失敗した修正が今回は成功するのか?
v1〜v6 は全て「アプリ側(フロントエンド)」の修正だったの。でも問題の原因は「通信の仕組みそのもの」。
アプリをいくら工夫しても、iPhoneが接続を切る以上、返事は受け取れない。
今回はサーバー側に「中継所」を作る。メッセージはまず中継所に預けて、中継所が独立して chibabotに届けてくれる。
結果も中継所が24時間保管。アプリは好きなタイミングで中継所に取りに行けばいいだけ。
通信モデルそのものを変えるから、根本的に解決できるのよ。