event-manual / chapter 6

イベントデータの取得

@event/fours-sdk@event/schema

fetchEvent — TTL キャッシュと last-good

fetchEvent(config, { slug?, ttlMs? })GET /slug/{eventSlug} を叩き、type === "event" のときだけ FourSEvent を返す。stub / mock-locked では null、失敗時も null(render を落とさない)。

キャッシュは SDK 内蔵の in-memory TTL(既定 60 秒)である。本番 payload は ~3.5MB で Next の fetch cache 上限(2MB)を超えるため Next data cache は実質効かない。warm な serverless インスタンス間では best-effort で共有される。さらに last-good 動作を持つ: 障害時の null は既存キャッシュが無いときだけ保存し、直前の正常値を消さない。

const event = res && res.type === "event" ? (res.data as FourSEvent) : null;
// 障害時に直前の正常値を消さない: null は既存キャッシュが無いときだけ保存
if (event || !hit) eventCache.set(slug, { at: Date.now(), event });
return event ?? hit?.event ?? null;

sessionSpeakerRefs — 新旧 API の吸収

4S の session↔speaker 参照には新旧2系統がある。sessionSpeakerRefs(raw) が唯一の入口:

detectModeratorId — 4S が唯一の真実源

detectModeratorId(raw, roleMatcher?)sessionSpeakers[].roleDEFAULT_MODERATOR_ROLE_RE = /moderat|モデレ|司会/i で照合し、order 順で最初に一致した speaker id を返す。CMS の手動上書き・「先頭を自動的にモデレーター扱い」はどちらも廃止済みの設計であり、Session.moderatorId毎回導出し、保存しない。イベント固有の表記は moderatorRoleMatcher オプションで上書きする。

adaptSession — overlay seam と last-writer-wins

ivs の 3-layer overlay(stage-meta / session-meta / KV)はイベント固有なので SDK に持ち込まない。代わりに overlay: (sessionId) => Partial<Session> コールバックを generic な継ぎ目として受け取り、@event/cms 側が content JSON / KV を注入する。

手動ピックアップ cardSpeakerIds と 4S 側 lineup 編集の競合は last-writer-wins で解決する。4S 側の基準時刻は fourSLineupEditedAt(raw)session.updatedAt と各 sessionSpeakers[].updatedAt の最大値。ISO-8601 UTC は辞書順比較が時刻順になる):

const fourSAt = fourSLineupEditedAt(raw);
const csi = overlay.cardSpeakerIds;
const csiAt = overlay.cardSpeakerIdsUpdatedAt;
const cardSpeakerWins = !!(csi && csi.length > 0 && (!csiAt || !fourSAt || csiAt >= fourSAt));

LOCKED フィールド(id / title / titleEn / startsAt / durationMin / roomId / speakerIds)は overlay のに spread されるため上書き不可。cardVariant は overlay の枠数が実登壇者数を下回ると登壇者が黙って欠けるため、枠数 >= 人数 のときだけ手動値を尊重する。

adaptSpeakernativeName 優先の氏名合成(pickNameJa / pickNameEn)、languages.en からの英語フィールド抽出、stripCorpName による法人格除去(既定 on、overlay 値には非適用)を行う。listSpeakersFromEvent は top-level speakers[] と session 埋め込みを結合し、同一 user の重複 speaker レコード(4S の既知挙動)を user 単位で畳む。

merge と safety guard

CMS content と 4S の合成は pure 関数で行う(xdeal 由来):

sync / 書き戻し時のデータ全損は safetyGuard({ existing, fresh, force }) が防ぐ:

条件判定
existing < 5書く(初期 seed フェーズ)
fresh = 0skip(4S 障害時の全消去防止)
fresh < existing × 30%skip(大幅減は要警戒。force で上書き可)
それ以外 / force書く

戻り値 GuardDecision は理由文字列を含み、cron ログにそのまま出せる。