Skip to content

日別記事 初期描画フロー

日別記事(daily_article)公開画面の初期描画フローを記録したドキュメントです。

プロジェクト構成(概要) の詳細です。ショートコードの一般的な MVC フローは ショートコードの処理の流れ を参照してください。

概要

日別記事の公開画面は、次の 2 系統 × 3 段階 で構成されています。

段階系統 A: ページ全体(DailyArticleTemplate)系統 B: 日別記事結果(DailyArticleResult ショートコード)
1. PHP 同期Twig テンプレート + ナビ用 link_day_data のみ(L1)プレースホルダー HTML + CSS/JS enqueue
2. キャッシュ共有データは warm REST で L2/Hash Transient を生成なし(ランキング等は REST 側で別キャッシュ)
3. JS 非同期warm → RelationalDay / MoveDayHall / MailImage 等を並列取得ランキング・ヒートマップ・末尾等を REST で取得

設計の要点

  • 初回 HTML では initialize_navigation() により 前日・翌日・前年リンク用の link_day_data を同期取得する(Issue #2182 Phase 1)。
  • 関連日・MoveDayHall・MailImage・日別記事結果は プレースホルダ + REST で遅延描画する。
  • daily_article_orchestrator.jswarm(POST)→ UI REST 並列 の順で制御する(Issue #2183 / #2185)。
  • 共有データ(主に daily_link_list + daily_data_kishu_list、加えて link_day_data も DTO に含む)の L2/Hash は warm_shared_template_data() で生成する。Shared L1($cached_data)は PHP static のため HTTP リクエストをまたいでは共有されない。warm_shared_template_data() は warm REST 内でも L1 に DTO を載せるが、後続の HTTP リクエスト(UI REST 等)へ引き継がれる永続化は L2/Hash Transient のみである。後続 UI REST では L2_HIT 時に同一リクエスト内で L1 に復元する。L2 ヒット時のハッシュ検証は compute_lightweight_data_hash() で行う。Hash Transient のデフォルト TTL は 300 秒(HASH_TRANSIENT_EXPIRATION、L2 Transient TTL と揃える。フィルター slot_kouryaku_daily_article_template_hash_transient_expiration で変更可)。link_day の insert/update/delete 時は push 型で対象日の L2 + Hash Transient を無効化する。

同期 / 遅延の境界

同期(初回 HTML に含める)

要素データ源備考
記事タイトルpost meta現状どおり
前日・翌日テキストリンクinitialize_navigation()Twig 上部ナビでは link_day_data.previous_day / next_day のみ表示。last_year はナビには出さず、MoveDayHallService 内で前年リンク生成(prev_year_post_data)に利用される。1 クエリ
月別リンク[MonthlyLinkByYear]既存 ShortCode(共有 warm とは独立)
考察・広告等既存 ShortCode同期は維持

遅延(DOMContentLoaded 以降)

要素REST備考
共有データ warmPOST /async-warm-template-dataHTML なし、L2/Hash 生成
関連日 + 日別カレンダーGET /async-relational-dayホール数分
MoveDayHallGET /async-move-day-hallホール数分(サムネ含む)
MailImageGET /async-mail-imageホール数分
ランキング等API-001-1, 3, 9 等DailyArticleResult 系

既存投稿本文に直書きされた [MailImage] ショートコードは同期のまま(テンプレート経路のみ非同期)。詳細は SC-007 を参照。

関連ファイル

役割パス
テンプレート入口core_src/Template/daily_article_template/components/DailyArticleTemplateContent.php
テンプレート Controllercore_src/Controller/daily_article_template_controller/DailyArticleTemplateController.php
実行 Servicecore_src/Service/daily_article_template_execution_service/DailyArticleTemplateExecutionService.php
共通データ Servicecore_src/Service/daily_article_template_data_service/DailyArticleTemplateDataService.php
Twig テンプレートcore_src/View/templates/daily_article_template/daily_article_template.twig
日別記事結果 ShortCodecore_src/short_code/daily_article_result/daily_article_result_short_code/DailyArticleResultShortCode.php
日別記事結果 Controllercore_src/Controller/daily_article_result_controller/DailyArticleResultController.php
非同期 JScore_src/View/templates/daily_article_result/daily_article_orchestrator.js
REST Handlercore_src/Handler/async_loading_handler/AsyncLoadingHandler.php
API 一覧docs/design/一覧/API-一覧.md

図 1: 全体俯瞰シーケンス

Browser から HTML 受信後、orchestrator が warm → UI REST を開始するまでの時系列です。

補足

  • 系統 A はページ全体を Twig で描画します。RelationalDay / MoveDayHall / MailImage は Twig 内のプレースホルダ div です。Twig 内の [CustomCode_CreateDailyArticleResult ...] 等は do_shortcode() で展開されます。
  • 系統 B の初回 HTML はプレースホルダーです。ランキング・ヒートマップ・末尾データの実データは orchestrator 経由の REST で後から取得します。
  • DailyArticleResultController.build_presentation() は REST 非同期用(service->execute() + ヒートマップレイアウト取得)であり、ショートコード初回 HTML では使われません。
  • DailyArticleTemplateDataService.initialize()initialize_navigation() + warm_shared_template_data() の一括実行用(deprecated)。初回 HTML では initialize_navigation() のみ呼ばれます。

図 2: warm_shared_template_data() キャッシュ分岐

共有データ(daily_link_list + daily_data_kishu_list + link_day_data)の取得経路です。POST /async-warm-template-data または各 UI REST Handler のフォールバックから呼ばれます。

キャッシュ層の定義

実装格納内容有効範囲
ナビ L1static $navigation_link_day_dataLinkDayData(前日・翌日・前年 URL)同一 HTTP リクエスト内のみ(initialize_navigation
L1(Shared)static $cached_dataDailyArticleTemplateDataPresentationDto同一 HTTP リクエスト内のみ
L2(Shared)WordPress Transients['dto' => DTO, 'data_hash' => string]リクエスト間(TTL 300 秒)
Hash TransientWordPress Transients(日付単位)SHA-256 ハッシュ文字列リクエスト間(デフォルト TTL 300 秒。フィルター slot_kouryaku_daily_article_template_hash_transient_expiration で変更可)

Transient TTL / cleanup 運用設計(Issue #2046)

項目設計
L2 Transient TTL300 秒(DailyArticleTemplateDataService::TRANSIENT_EXPIRATION)。date + halls ごとに 1 キー。
Hash Transient TTL300 秒(DailyArticleTemplateDataService::HASH_TRANSIENT_EXPIRATION、フィルターで変更可)。date ごとに 1 キー。
想定エントリ数同時滞留キーは概ね「直近 TTL 区間でアクセスされた date + halls 件数 + date 件数」。TTL 経過で期限切れ化。
定期掃除TransientCleanupScheduler が daily cron(slot_kouryaku_daily_transient_cleanup)で delete_expired_transients( true ) を実行。
多重実行対策slot_kouryaku_transient_cleanup_lock(1時間TTL)で二重実行を抑止。stale / 不正ロックは回収して再試行。

この設計により、期限切れ transient の残存は短TTL + 定期 cleanup で収束し、wp_options 肥大化リスクを抑える。

分岐パス一覧

パスDB アクセス備考
NAV_L1_HITなしナビ用 link_day_data を static から利用
NAV_FETCHfetch_link_day_data 1 本初回 HTML 同期時
L1_HIT(Shared)なしstatic 変数から DTO をそのまま利用
L2_HIT原則なし(Hash Transient ミス時のみ集約 stats 2 本)Transient から DTO 復元 → L1 に載せ替え
L2_HASH_MISMATCHあり(DB_FETCH へ)L2・Hash Transient を削除
L2_MISS / L2_INVALIDあり(DB_FETCH へ)古い L2 を削除して下へ
DB_FETCHフル取得link 一覧、機種サマリ、link_day → L1/L2/Hash Transient 保存

ハッシュ検証の目的

L2 は 5 分 TTL のため、phpMyAdmin 等の DB 直接変更を Transient 期限だけでは検知できません。compute_lightweight_data_hash() / compute_data_hash_from_fetched_data() で SHA-256 ハッシュを計算し、L2 に保存した data_hash と照合します(Issue #2175 / #2170)。Hash Transient が有効な間(デフォルト最大 300 秒)は DB 変更を即時検知しません。link_day の URL/event 更新は push 型無効化で検知します。


図 3: JS orchestrator シーケンス

daily_article_orchestrator.js が DOMContentLoaded 後に warm → UI REST を呼び出す流れです。

orchestrator のルール

  1. warm 完了(または失敗待機)後に UI REST を並列発火 — キャッシュスタンピード防止
  2. warm 中はプレースホルダ表示のまま
  3. warm 失敗時も UI REST をそのまま並列発火(各 Handler が warm_shared_template_data で個別フォールバック)
  4. UI REST のレスポンスは生 HTML ではなく JSON(parseJsonResponse()data.html を DOM に反映。テンプレート断片系は data.assets も読み込む)

REST エンドポイント

ベース URL: /wp-json/daily-article/v1/dailyArticleAsync.restUrl 経由)

コードパスmethodトリガー用途
API-001-10/async-warm-template-dataPOSTページ読み込み直後共有データ L2 warm(HTML なし)
API-001-11/async-relational-dayGETページ読み込み直後関連日 + 日別カレンダー
API-001-12/async-move-day-hallGETページ読み込み直後MoveDayHall
API-001-13/async-mail-imageGETページ読み込み直後MailImage
API-001-9/async-heatmap-simpleGETページ読み込み直後ヒートマップ簡易
API-001-1/async-rankingGETページ読み込み直後ランキング
API-001-3/async-end-numberGETページ読み込み直後末尾データ
API-001-2/async-heatmap-detailGET詳細ボタン初回クリックヒートマップ詳細
API-001-4/async-kishu-searchGET検索ボタンクリック機種指定データ検索
API-001-14/async-kishudataGETページ読み込み直後機種データ(SC-009)

権限: 上記 Async 系は nonce + IP レート制限(60 秒 10 回)。詳細は API-一覧.md を参照。

PHP → JS データ受け渡し

core_src/View/templates/daily_article_result/index.phpwp_localize_script で以下を渡します。

キー内容
restUrlrest_url('daily-article/v1/')
noncewp_create_nonce('wp_rest')
msgRankingFailed非同期エラー文言

Twig ルート要素 .daily-article-templatedata-warm-date / data-warm-halls が warm リクエストの入力です。


Twig プレースホルダ

daily_article_template.twig では次のプレースホルダを使用します。

要素CSS クラスdata 属性(例)
MailImagemail-image-placeholderdata-hall, data-date
MoveDayHallmove-day-hall-placeholderdata-hall, data-date, data-preday, data-nextday
RelationalDayrelational-day-placeholderdata-hall, data-date
DailyArticleResult既存プレースホルダクラスdata-hall, data-date

関連ドキュメント