Spec
Requirement: index.json の TTL ベースキャッシュ¶
DataFetcher は fetchIndex() の成功レスポンスをインメモリキャッシュに保存し、TTL(デフォルト 30,000ms)以内の再リクエストではキャッシュから返却しなければならない(SHALL)。TTL 超過時はネットワークから再取得してキャッシュを更新しなければならない(SHALL)。失敗レスポンス(ok: false)はキャッシュしない。
また、DataFetcher は index.json キャッシュを明示的に無効化する手段を提供しなければならない(MUST)。明示的に無効化された後の次回 fetchIndex() は、TTL 内であってもネットワークリクエストを発行しなければならない(MUST)。
Scenario: TTL 内のキャッシュヒット¶
- WHEN
fetchIndex()が成功した後、TTL 以内に再度fetchIndex()が呼ばれる - THEN ネットワークリクエストを発行せず、キャッシュされたデータを返却する
Scenario: TTL 超過後のキャッシュミス¶
- WHEN
fetchIndex()が成功した後、TTL を超過してから再度fetchIndex()が呼ばれる - THEN 新しいネットワークリクエストを発行し、キャッシュを更新する
Scenario: 失敗レスポンスの非キャッシュ¶
- WHEN
fetchIndex()がエラーレスポンス(HTTP エラーまたはネットワークエラー)を返した - THEN そのレスポンスをキャッシュに保存しない
- THEN 次回の
fetchIndex()呼び出しはネットワークリクエストを発行する
Scenario: 明示的無効化後の再取得¶
- WHEN
fetchIndex()が成功して TTL 内キャッシュが存在する状態でinvalidateIndexCache()が呼ばれる - THEN 次回の
fetchIndex()は TTL 内であっても新しいネットワークリクエストを発行する - THEN 取得成功時に新しいレスポンスでキャッシュを更新する
Requirement: セッション JSON の永続キャッシュ¶
DataFetcher は fetchSession(sessionId) の成功レスポンスをインメモリキャッシュに保存し、同一 sessionId の再リクエストでは常にキャッシュから返却する。セッション JSON は不変リソースのため、TTL は設けない。失敗レスポンス(ok: false)はキャッシュしない。
Scenario: セッションデータのキャッシュヒット¶
- WHEN
fetchSession('abc12345')が成功した後、再度fetchSession('abc12345')が呼ばれる - THEN ネットワークリクエストを発行せず、キャッシュされたデータを返却する
Scenario: 異なるセッション ID はキャッシュミス¶
- WHEN
fetchSession('abc12345')が成功した後、fetchSession('def67890')が呼ばれる - THEN
def67890に対して新しいネットワークリクエストを発行する
Scenario: セッション取得失敗時の非キャッシュ¶
- WHEN
fetchSession(sessionId)がエラーレスポンスを返した - THEN そのレスポンスをキャッシュに保存しない
- THEN 同一 sessionId の次回呼び出しはネットワークリクエストを発行する
Requirement: 同一 URL リクエストの重複排除¶
DataFetcher は同一 URL に対する同時リクエストを 1 つの Promise に統合する。最初のリクエストが完了するまで、同じ URL への追加リクエストは新しい fetch を発行せず、最初のリクエストの Promise を共有する。Promise が解決した後、inflight エントリは削除される。
Scenario: 同時リクエストの統合¶
- WHEN
fetchSession('abc12345')が応答を待っている間に、再度fetchSession('abc12345')が呼ばれる - THEN 2 回目の呼び出しは新しい fetch を発行しない
- THEN 両方の呼び出しが同一の結果を受け取る
Scenario: 順次リクエストは別々に処理¶
- WHEN
fetchSession('abc12345')が完了した後に、再度fetchSession('abc12345')が呼ばれる(キャッシュが無い場合) - THEN 新しい fetch リクエストを発行する
Scenario: 異なる URL は重複排除しない¶
- WHEN
fetchSession('abc12345')とfetchSession('def67890')が同時に呼ばれる - THEN それぞれ別々の fetch リクエストを発行する
Requirement: TTL のコンストラクタ設定¶
DataFetcher のコンストラクタは indexTtl オプションを受け取り、index.json キャッシュの TTL(ミリ秒)を設定できる。省略時はデフォルト値 30,000ms を使用する。
Scenario: カスタム TTL の指定¶
- WHEN
new DataFetcher({ indexTtl: 5000 })でインスタンスを作成する - THEN
index.jsonのキャッシュ TTL が 5,000ms になる
Scenario: デフォルト TTL の使用¶
- WHEN
new DataFetcher()でインスタンスを作成する - THEN
index.jsonのキャッシュ TTL がデフォルトの 30,000ms になる
Requirement: 公開 API の後方互換性¶
DataFetcher の公開メソッド fetchIndex() と fetchSession(sessionId) の戻り値の型(Promise<{ok: true, data: object} | {ok: false, error: string}>)は変更してはならない(MUST NOT)。既存の呼び出し元コードは修正不要で動作しなければならない(SHALL)。
DataFetcher は追加の公開メソッド invalidateIndexCache() を提供し、既存の fetchIndex() / fetchSession() 利用を破壊してはならない(MUST NOT)。
Scenario: fetchIndex の戻り値型が維持される¶
- WHEN キャッシュ導入後に
fetchIndex()を呼び出す - THEN 戻り値は
{ ok: true, data: object }または{ ok: false, error: string }のいずれかである
Scenario: fetchSession の戻り値型が維持される¶
- WHEN キャッシュ導入後に
fetchSession(sessionId)を呼び出す - THEN 戻り値は
{ ok: true, data: object }または{ ok: false, error: string }のいずれかである
Scenario: invalidateIndexCache 追加後も既存呼び出しは動作する¶
- WHEN
invalidateIndexCache()を呼び出した後にfetchIndex()とfetchSession(sessionId)を呼び出す - THEN 既存メソッドは従来どおりの戻り値型で結果を返す