Yuki Takei 4 месяцев назад
Родитель
Сommit
92d29c4ab7
1 измененных файлов с 44 добавлено и 4 удалено
  1. 44 4
      .serena/memories/apps-app-page-tree-specification.md

+ 44 - 4
.serena/memories/apps-app-page-tree-specification.md

@@ -277,10 +277,22 @@ const { isCreatingChild, CreateInputComponent, startCreating } = usePageCreate(i
 
 **実装ファイル**:
 - `features/page-tree/hooks/use-socket-update-desc-count.ts`
+- `features/page-tree/states/page-tree-desc-count-map.ts`
+- `features/page-tree/states/page-tree-update.ts`
 
-#### 機能概要
+#### 設計方針
+
+**descendantCountバッジの更新** と **ツリー構造の更新** は別々の関心事として分離:
+
+| 更新タイプ | トリガー | 動作 | 対象 |
+|-----------|---------|------|------|
+| バッジ更新 | Socket.io `UpdateDescCount` | 数字のみ更新(軽量) | 全祖先 |
+| ツリー構造更新 | リロードボタン / 自分の操作後 | 子リスト再取得(重い) | 操作した本人のみ |
 
-Socket.ioを使用して、他のクライアントからのページ変更(作成、削除、移動)をリアルタイムで反映する機能。
+**この分離の理由:**
+- 大規模環境で多くのユーザーが同時に操作する場合、全員のツリーが頻繁に再構築されるとパフォーマンス問題が発生
+- バッジ(数字)の更新は軽量なので全員にリアルタイム反映してもOK
+- ツリー構造の変更は操作した本人のウィンドウのみで即時反映し、他ユーザーはリロードボタンで対応
 
 #### 使用方法
 
@@ -296,6 +308,7 @@ useSocketUpdateDescCount();
 - `UpdateDescCount`: ページの子孫カウント(descendantCount)の更新
   - サーバーからページ作成/削除/移動時に発行される
   - 受信データ(Record形式)をMap形式に変換してJotai stateに保存
+  - **バッジ表示のみ更新、ツリー構造は更新しない**
 
 #### 実装詳細
 
@@ -308,6 +321,7 @@ export const useSocketUpdateDescCount = (): void => {
     if (socket == null) return;
 
     const handler = (data: UpdateDescCountRawData) => {
+      // バッジの数字のみ更新(ツリー構造は更新しない)
       const newData: UpdateDescCountData = new Map(Object.entries(data));
       updatePtDescCountMap(newData);
     };
@@ -318,11 +332,36 @@ export const useSocketUpdateDescCount = (): void => {
 };
 ```
 
+#### ツリー構造の更新
+
+ツリー構造(子リスト)の更新は以下のタイミングで行われる:
+
+1. **リロードボタン**: `notifyUpdateAllTrees()` を呼び出し、全ツリーを再取得
+2. **自分の操作後**: 
+   - Create/Delete/Move操作の完了コールバックで `notifyUpdateItems([parentId])` を呼び出し
+   - 操作した親ノードの子リストのみ再取得
+
+```typescript
+// リロードボタンの例
+const { notifyUpdateAllTrees } = usePageTreeInformationUpdate();
+const handleReload = () => notifyUpdateAllTrees();
+
+// 操作完了後の例(Create, Delete, Move)
+const { notifyUpdateItems } = usePageTreeInformationUpdate();
+const handleOperationComplete = (parentId: string) => notifyUpdateItems([parentId]);
+```
+
 #### 関連状態
 
 - `page-tree-desc-count-map.ts`: 子孫カウントを管理するJotai atom
-  - `usePageTreeDescCountMap()`: カウント取得
-  - `usePageTreeDescCountMapAction()`: カウント更新
+  - `usePageTreeDescCountMap()`: カウント取得(バッジ表示用)
+  - `usePageTreeDescCountMapAction()`: カウント更新(Socket.ioから)
+
+- `page-tree-update.ts`: ツリー更新を管理するJotai atom
+  - `generationAtom`: 更新世代番号
+  - `lastUpdatedItemIdsAtom`: 更新対象アイテムID(nullは全体更新)
+  - `usePageTreeInformationUpdate()`: 更新通知(notifyUpdateItems, notifyUpdateAllTrees)
+  - `usePageTreeRevalidationEffect()`: 更新検知と再取得実行
 
 ### 3.5 Checkboxes(AI Assistant用)
 
@@ -617,3 +656,4 @@ await mutatePageTree();
 - 2025-12-08: Drag and Drop実装完了、ディレクトリ構成更新
 - 2025-12-08: リアルタイム更新(Socket.io統合)実装完了
 - 2025-12-08: headless-tree キャッシュ無効化の知見を追加(invalidateChildrenIds の optimistic パラメータ)
+- 2025-12-08: Socket.io更新の設計方針を明確化(バッジ更新とツリー構造更新の分離)