File size: 8,710 Bytes
68f7925
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# Gradio API フェッチシーケンス仕様書

## 概要

本ドキュメントは、改善案生成画面におけるGradio APIの呼び出しシーケンス、キャッシュ管理、および再フェッチ戦略について定義します。

## アーキテクチャ概要

### 主要コンポーネント

1. **useProposalTabsOptimized** - 統合クエリ管理フック
2. **個別クエリフック**
   - useThemeByMomentOptimized
   - useProposalFv
   - useProposalCn
   - useProposalPrediction
   - useProposalIntent
3. **キャッシュ管理** - Tanstack Query + MD5ハッシュベースキー

## API呼び出しシーケンス

### 1. 基本フロー

```mermaid
sequenceDiagram
    participant User
    participant Component
    participant ThemeByMoment
    participant FV
    participant CN
    participant Prediction
    participant Intent

    User->>Component: 改善案画面を開く
    Component->>ThemeByMoment: ①テーマ取得
    ThemeByMoment-->>Component: strategy_x_moment返却

    par 並列実行
        Component->>FV: ②FV提案取得
        Component->>CN: ②CN提案取得
    end

    FV-->>Component: FVデータ
    CN-->>Component: CNデータ

    par 並列実行
        Component->>Prediction: ③予測取得(FV+CNデータ利用)
        Component->>Intent: ③インテント取得(FV+CNデータ利用)
    end

    Prediction-->>Component: 予測データ
    Intent-->>Component: インテントデータ
    Component-->>User: 改善案表示
```

### 2. 依存関係

```mermaid
graph TD
    A[ThemeByMoment] --> B[strategy_x_moment]
    B --> C[ProposalFv]
    B --> D[ProposalCn]
    C --> E[ProposalPrediction]
    D --> E
    C --> F[ProposalIntent]
    D --> F

    style A fill:#f9f,stroke:#333,stroke-width:2px
    style E fill:#9ff,stroke:#333,stroke-width:2px
    style F fill:#9ff,stroke:#333,stroke-width:2px
```

## キャッシュキー設計

### 1. キャッシュキー構造

```typescript
// 基本構造(選択データに依存するAPI)
[apiName, selectionHash]

// 具体例
['themeByMoment', 'abc123...']                    // selectionに依存
['proposalFv', 'abc123...']                       // selectionに依存
['proposalCn', 'abc123...']                       // selectionに依存
['proposalPrediction', 'abc123...']               // selectionに依存
['proposalIntent', 'abc123...']                   // selectionに依存
```

### 2. ハッシュ生成ロジック

```typescript
// 選択データのハッシュ(全API共通)
selectionHash = MD5({
  selectedMoments,
  fvInfos,
  cnInfo
})
```

**重要な設計原則**:
- 全てのAPIで`selectionHash`のみをキャッシュキーに使用
- `triggerVersion`はキャッシュキーに含めない(確定ボタンを押しても再フェッチしない)
- Prediction/IntentもFV/CNデータハッシュではなく`selectionHash`を使用
- FV/CNの値が更新されても、同じ選択肢なら再フェッチしない

**Prediction/Intentの実行制御**:
```typescript
// lastFetchedSelectionHashRefで追跡
const canStartPredictionIntent =
  proposalFv.isSuccess &&
  proposalCn.isSuccess &&
  lastFetchedSelectionHashRef.current === selectionHash;
```

## 再フェッチ条件

### 1. 自動再フェッチトリガー

```mermaid
flowchart TD
    Start([開始])

    TriggerChange{triggerVersion<br/>変更?}
    SelectionChange{選択データ<br/>変更?}
    FvCnChange{FV/CNデータ<br/>変更?}

    ClearOldCache[古いキャッシュクリア]
    RefetchAll[全API再実行]
    RefetchPredIntent[Prediction/Intent<br/>のみ再実行]

    Start --> TriggerChange
    Start --> SelectionChange
    Start --> FvCnChange

    TriggerChange -->|Yes| ClearOldCache
    SelectionChange -->|Yes| ClearOldCache
    ClearOldCache --> RefetchAll

    FvCnChange -->|Yes| RefetchPredIntent

    TriggerChange -->|No| End([終了])
    SelectionChange -->|No| End
    FvCnChange -->|No| End
```

### 2. 再フェッチ条件詳細

| トリガー | 影響範囲 | 説明 |
|---------|---------|------|
| selectionHash変更 | 全API | 選択モーメント/FV情報が変わった時 |
| FV/CN成功後 | Prediction/Intentが実行 | selectionHashが同じ場合は実行されない |
| エラー時自動リトライ | 該当APIのみ | 2秒後に自動リトライ(最大2回) |

**重要な変更点**:
- `triggerVersion`(確定ボタン)での再フェッチを廃止
- Prediction/IntentはselectionHashが変わった時のみ、新しいFV/CNデータで実行
- selectionHashが同じ場合、FV/CNが更新されてもPrediction/Intentは再実行しない

## キャッシュ管理戦略

### 1. キャッシュライフサイクル

```mermaid
stateDiagram-v2
    [*] --> Fresh: 初回フェッチ
    Fresh --> Stale: staleTime経過(30分)
    Stale --> Fresh: 再フェッチ
    Stale --> Garbage: gcTime経過(60分)
    Garbage --> [*]: メモリから削除

    Fresh --> Canceled: キャンセル
    Stale --> Canceled: キャンセル
    Canceled --> [*]: 即削除
```

### 2. キャッシュキーによる自動管理

**重要**: selectionHashのみでキャッシュを管理、triggerVersionは使用しない

```typescript
// 全APIで統一されたキャッシュキー構造
const cacheKey = [
  'apiName',
  selectionHash      // 選択データ変更時のみ新しいキーになる
];

// 例
['proposalFv', 'abc123...']
['proposalCn', 'abc123...']
['proposalPrediction', 'abc123...']
['proposalIntent', 'abc123...']
```

**Prediction/Intent実行制御**:
```typescript
// selectionHashが変わった時の新しいFV/CNデータであることを確認
const canStartPredictionIntent =
  proposalFv.isSuccess &&
  proposalCn.isSuccess &&
  lastFetchedSelectionHash === selectionHash;
```

### 3. 最適化されたクリーンアップ

```typescript
// コンポーネントアンマウント時のみ実行中クエリをキャンセル
useEffect(() => {
  return () => {
    // アクティブなクエリをキャンセル(ネットワーク負荷軽減)
    queryClient.cancelQueries({ queryKey: 現在のキー });
  };
}, []);

// 古いキャッシュはgcTimeで自動削除(明示的削除は不要)
```

## エラーハンドリング

### 1. 自動リトライ

```typescript
// Prediction/Intentは自動リトライ
useEffect(() => {
  if (proposalPrediction.isError && !proposalPrediction.isFetching) {
    setTimeout(() => {
      proposalPrediction.refetch();
    }, 2000); // 2秒後
  }
}, [proposalPrediction]);
```

### 2. 部分的失敗の処理

- 各APIは独立して管理
- 失敗したAPIのみ再実行可能
- 他のAPIの成功データは保持

## パフォーマンス最適化

### 1. 並列実行

- FV/CNは並列実行
- Prediction/Intentも並列実行
- 依存関係がないAPIは同時実行

### 2. キャッシュ共有

- 同一キーのデータはタブ間で共有
- staleTime: 30分(データ新鮮期間)
- gcTime: 60分(ガベージコレクション)

### 3. 不要なフェッチの防止

- ダミーモードではThemeByMomentをスキップ
- enabledフラグで条件付き実行
- キャッシュヒット時は再フェッチしない

## 実装ファイル

| ファイル | 役割 |
|---------|------|
| `/api-client/proposal/proposal/optimized-queries.ts` | 統合クエリ管理 |
| `/api-client/proposal/proposal/individual-queries.ts` | 個別クエリフック |
| `/services/gradio-with-dummy.ts` | API呼び出し関数 |
| `/store/proposal-trigger.ts` | トリガー管理とハッシュ生成 |

## 使用例

```typescript
// 改善案画面での使用
const {
  data: proposalTabsData,
  rawData: proposalRawData,
  isLoading,
  isError,
  refetch,
  refetchAll
} = useProposalTabsOptimized({
  strategy_x_moment: strategyXMoment,
  enabled: selectedMoments.length > 0,
  dummyMode: isDummyMode,
});
```

## 注意事項

1. **キャッシュキーの一意性**
   - MD5ハッシュで一意性を保証
   - データ変更時は必ず新しいキーになる

2. **メモリ管理**
   - アンマウント時にクエリをキャンセル
   - 古いキャッシュは自動削除

3. **エラー処理**
   - 部分的な失敗に対応
   - 自動リトライ機能付き

## 更新履歴

- 2024-01-21: 初版作成
  - 個別API管理の実装
  - MD5ハッシュベースのキャッシュキー
  - 依存関係に基づく自動再フェッチ

- 2024-01-22: キャッシュキー最適化
  - triggerVersionをキャッシュキーから削除
  - selectionHashのみでキャッシュ管理
  - Prediction/Intentの実行条件を厳密化
  - 不要な再フェッチを防止