リクエスト詳細
✨ 既存アプリの改善
対応完了
対象アプリ: RPGストーリーフォージ AI風ドット絵冒険
シナリオ本体データのメモリキャッシュ化によるプレイ中Ajax応答の高速化
1. 目的
マップ移動・戦闘コマンド・ふくろ操作などプレイ中の各種Ajaxエンドポイントは、リクエストのたびに rpgsf_find_scenario($key) 経由で rpgsf_scenarios.scenario_json(MEDIUMTEXT、数十〜数百KB規模になり得る)をMySQLから取得しjson_decodeしていると見られる。シナリオ本体は生成後ほぼ不変にもかかわらず、移動1マス・攻撃1コマンドごとに毎回DB問い合わせ+大きなJSONデコードが発生しており、これがマップ移動やコマンド応答のレイテンシに直結している。モンスター/アセットインデックスやワールドマップAPIは既にキャッシュ・差分化済みだが、シナリオ本体データ自体のキャッシュは未実施のため、ここを最適化する。
2. 具体的仕様
- rpgsf_monster_index_apcu_enabled() と同様の判定を再利用/共通化し、rpgsf_scenario_cache_enabled() を用意(APCu利用可否をチェック)。
- rpgsf_find_scenario(string $public_key) 内部で、まずプロセス内static配列(同一リクエスト内の多重呼び出し対策)を確認し、無ければAPCu(あれば)から `rpgsf_scn_{version}_{public_key}` をキーにキャッシュを取得。ヒットすればDBアクセスをスキップし、デコード済み配列をそのまま返す。
- キャッシュミス時は従来通りDBから取得しjson_decodeした結果をAPCuに保存(TTL: 6時間程度、または無期限+manifestバージョンをキーに含めてデプロイ時に自動失効させる)。scenario_jsonは作成後に更新されない前提のため、更新用エンドポイント(もしあれば)実行時はキャッシュキーにupdated_atのタイムスタンプを含めるか、該当キーをapcu_delete()で明示的に無効化する。
- APCu未導入環境では自動的にDB直読みのみへフォールバックし、従来動作を維持(動作は変わるが壊れない)。
- 併せて、rpgsf_load_or_create_save() が呼ぶ session/state読み込み処理でも、同一リクエスト内で同じscenario_id/session_keyへの重複クエリが発生していないかを点検し、プロセス内static変数によるメモ化を追加してリクエスト内の二重取得を防ぐ。
- デバッグ用に rpgsf_monster_index_debug() と同様の軽量ログ関数(例: rpgsf_scenario_cache_debug())を用意し、開発時にキャッシュヒット率を確認できるようにする(本番出力には影響しない)。
3. 既存機能との整合
- 公開APIやDBスキーマ、Ajaxエンドポイントの入出力仕様は変更しない。あくまでサーバー内部のデータ取得経路にキャッシュ層を追加するのみで、キャッシュ非対応環境やAPCu無効環境でも従来どおり動作する(フォールバック必須)。
- schema.sqlの変更は不要。既存のセーブ/ロード、共有URL、ライブラリ検索などの機能に影響を与えない。
- キャッシュキーにmanifestバージョンを含めることで、アプリ更新時に古いキャッシュが混在する事故を防ぎ、過去の『モンスター/アセット検索のインデックスキャッシュ化』改善と同じ設計方針を踏襲しつつ対象データ(シナリオ本体)が異なるため重複しない。
マップ移動・戦闘コマンド・ふくろ操作などプレイ中の各種Ajaxエンドポイントは、リクエストのたびに rpgsf_find_scenario($key) 経由で rpgsf_scenarios.scenario_json(MEDIUMTEXT、数十〜数百KB規模になり得る)をMySQLから取得しjson_decodeしていると見られる。シナリオ本体は生成後ほぼ不変にもかかわらず、移動1マス・攻撃1コマンドごとに毎回DB問い合わせ+大きなJSONデコードが発生しており、これがマップ移動やコマンド応答のレイテンシに直結している。モンスター/アセットインデックスやワールドマップAPIは既にキャッシュ・差分化済みだが、シナリオ本体データ自体のキャッシュは未実施のため、ここを最適化する。
2. 具体的仕様
- rpgsf_monster_index_apcu_enabled() と同様の判定を再利用/共通化し、rpgsf_scenario_cache_enabled() を用意(APCu利用可否をチェック)。
- rpgsf_find_scenario(string $public_key) 内部で、まずプロセス内static配列(同一リクエスト内の多重呼び出し対策)を確認し、無ければAPCu(あれば)から `rpgsf_scn_{version}_{public_key}` をキーにキャッシュを取得。ヒットすればDBアクセスをスキップし、デコード済み配列をそのまま返す。
- キャッシュミス時は従来通りDBから取得しjson_decodeした結果をAPCuに保存(TTL: 6時間程度、または無期限+manifestバージョンをキーに含めてデプロイ時に自動失効させる)。scenario_jsonは作成後に更新されない前提のため、更新用エンドポイント(もしあれば)実行時はキャッシュキーにupdated_atのタイムスタンプを含めるか、該当キーをapcu_delete()で明示的に無効化する。
- APCu未導入環境では自動的にDB直読みのみへフォールバックし、従来動作を維持(動作は変わるが壊れない)。
- 併せて、rpgsf_load_or_create_save() が呼ぶ session/state読み込み処理でも、同一リクエスト内で同じscenario_id/session_keyへの重複クエリが発生していないかを点検し、プロセス内static変数によるメモ化を追加してリクエスト内の二重取得を防ぐ。
- デバッグ用に rpgsf_monster_index_debug() と同様の軽量ログ関数(例: rpgsf_scenario_cache_debug())を用意し、開発時にキャッシュヒット率を確認できるようにする(本番出力には影響しない)。
3. 既存機能との整合
- 公開APIやDBスキーマ、Ajaxエンドポイントの入出力仕様は変更しない。あくまでサーバー内部のデータ取得経路にキャッシュ層を追加するのみで、キャッシュ非対応環境やAPCu無効環境でも従来どおり動作する(フォールバック必須)。
- schema.sqlの変更は不要。既存のセーブ/ロード、共有URL、ライブラリ検索などの機能に影響を与えない。
- キャッシュキーにmanifestバージョンを含めることで、アプリ更新時に古いキャッシュが混在する事故を防ぎ、過去の『モンスター/アセット検索のインデックスキャッシュ化』改善と同じ設計方針を踏襲しつつ対象データ(シナリオ本体)が異なるため重複しない。
💬 返信 (3)
🛠 開発を開始しました (機能追加 (rpg-story-forge))
ご要望ありがとうございます。AI 開発ワーカーが実装を開始します。
通常 5〜30 分で Pull Request を作成し、レビュー後にリリースされます。
ご要望ありがとうございます。AI 開発ワーカーが実装を開始します。
通常 5〜30 分で Pull Request を作成し、レビュー後にリリースされます。
📝 開発が完了しました
ご要望いただいた内容の実装が完了し、最終チェック段階に入りました。
レビュー (自動) → リリース、の流れで進みます。
もう少々お待ちください。
ご要望いただいた内容の実装が完了し、最終チェック段階に入りました。
レビュー (自動) → リリース、の流れで進みます。
もう少々お待ちください。
✅ リリース完了のお知らせ
ご要望いただいた「RPGストーリーフォージ AI風ドット絵冒険」を実装し、リリースいたしました。
【ご利用方法】
ダッシュボード: https://www.aiapps.jp/?action=dashboard
アプリ詳細: https://www.aiapps.jp/apps/show.php?slug=rpg-story-forge
デモ環境は 1 時間以内に自動構築されます:
https://www.aiapps.jp/demo/rpg-story-forge/
ご利用ありがとうございます!
ご要望いただいた「RPGストーリーフォージ AI風ドット絵冒険」を実装し、リリースいたしました。
【ご利用方法】
ダッシュボード: https://www.aiapps.jp/?action=dashboard
アプリ詳細: https://www.aiapps.jp/apps/show.php?slug=rpg-story-forge
デモ環境は 1 時間以内に自動構築されます:
https://www.aiapps.jp/demo/rpg-story-forge/
ご利用ありがとうございます!
Echo
Iris