# 機能設計書 16-リーディングリスト同期

## 概要

本ドキュメントは、Wikipedia iOSアプリにおける「リーディングリスト同期」機能の設計を記述する。この機能は、ログイン済みユーザーのリーディングリストをWikipediaサーバーと同期し、複数デバイス間でデータを共有するものである。

### 本機能の処理概要

**業務上の目的・背景**：ユーザーがiPhone、iPadなど複数のデバイスでWikipediaアプリを使用する場合、リーディングリストを同期することで、どのデバイスからでも同じ保存記事にアクセスできるようにする。また、デバイスの紛失や交換時にもデータを復元できるようにする。

**機能の利用シーン**：ログイン済みユーザーがリーディングリストを変更（追加/編集/削除）すると、バックグラウンドでWikipediaサーバーと同期が行われる。アプリ起動時や特定のタイミングでサーバーからの変更も取得する。

**主要な処理内容**：
1. ローカル変更をサーバーにアップロード
2. サーバー変更をローカルにダウンロード
3. コンフリクト解決
4. 同期状態の管理
5. 同期エラーの処理とリトライ

**関連システム・外部連携**：Wikipedia Reading Lists API（/data/lists/エンドポイント）と連携。CSRFトークン認証を使用してAPI呼び出しを行う。

**権限による制御**：ログイン済みユーザーのみ利用可能。同期を有効にするためにはSettings画面からの設定が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | Settings画面 | 設定画面 | 同期の有効/無効設定 |

## 機能種別

バックグラウンド同期 / API通信 / データマージ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| syncState | ReadingListSyncState | Yes | 同期状態フラグ | - |
| csrfToken | String | Yes | CSRF認証トークン | 有効なトークンであること |

### 入力データソース

- ローカルデータ：Core Data（未同期のReadingList, ReadingListEntry）
- サーバーデータ：Wikipedia Reading Lists API

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| syncedReadingListsCount | Int | 同期されたリスト数 |
| syncedReadingListEntriesCount | Int | 同期されたエントリ数 |
| error | Error? | 同期エラー |

### 出力先

- Core Data：同期済みデータの更新
- 通知：syncDidFinishNotification

## 処理フロー

### 処理シーケンス

```
1. 同期開始トリガー
   └─ sync() メソッド呼び出し
2. 同期状態チェック
   └─ ReadingListSyncStateで必要な処理を判定
3. リモート有効化（初回）
   └─ APIでsetup呼び出し
4. ローカル変更のアップロード
   └─ 未同期のリスト・エントリをAPI経由で送信
5. サーバー変更のダウンロード
   └─ APIから変更を取得してCore Dataに反映
6. 同期完了通知
   └─ syncDidFinishNotificationを発行
```

### フローチャート

```mermaid
flowchart TD
    A[同期トリガー] --> B{ログイン済み?}
    B -->|No| C[処理終了]
    B -->|Yes| D{同期有効?}
    D -->|No| C
    D -->|Yes| E[同期状態チェック]
    E --> F{初回同期?}
    F -->|Yes| G[setup API呼び出し]
    F -->|No| H[ローカル変更取得]
    G --> H
    H --> I[変更をサーバーに送信]
    I --> J[サーバー変更を取得]
    J --> K[Core Dataに反映]
    K --> L[同期完了通知]
    L --> M{エラー発生?}
    M -->|Yes| N[エラー処理]
    M -->|No| O[処理完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-16-01 | 同期要件 | ログイン済み かつ 同期有効設定 | 同期実行時 |
| BR-16-02 | バッチサイズ | 1リクエストあたり500件まで | API呼び出し時 |
| BR-16-03 | フルシンク閾値 | 更新件数が1000件超の場合はフルシンク | 増分同期時 |
| BR-16-04 | コンフリクト解決 | サーバー優先で解決 | データ競合時 |
| BR-16-05 | デフォルトリスト | リモートIDが設定されていない場合は作成 | 初回同期時 |

### 計算ロジック

バッチ処理:
```swift
// バッチサイズ制限
let WMFReadingListBatchSizePerRequestLimit = 500
let WMFReadingListCoreDataBatchSize = 500
```

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ローカル変更取得 | ReadingList, ReadingListEntry | SELECT | 未同期データを取得 |
| サーバー変更反映 | ReadingList, ReadingListEntry | INSERT/UPDATE/DELETE | サーバーデータを反映 |
| 同期状態更新 | ReadingList, ReadingListEntry | UPDATE | remoteId, isUpdatedLocally更新 |

### テーブル別操作詳細

#### ReadingList

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | isUpdatedLocally | true | 未同期リスト取得 |
| UPDATE | readingListID | リモートID | 同期後 |
| UPDATE | isUpdatedLocally | false | 同期完了後 |

#### ReadingListEntry

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | isUpdatedLocally | true | 未同期エントリ取得 |
| UPDATE | readingListEntryID | リモートID | 同期後 |
| UPDATE | isUpdatedLocally | false | 同期完了後 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| notLoggedIn | 認証エラー | 未ログイン状態 | ログイン促進 |
| badtoken | 認証エラー | CSRFトークン無効 | トークン再取得 |
| notSetup | 初期化エラー | 同期未セットアップ | setup API呼び出し |
| listLimit | ビジネスエラー | リスト数上限超過 | エラー表示 |
| entryLimit | ビジネスエラー | エントリ数上限超過 | エラー表示 |
| needsFullSync | 同期エラー | 増分同期失敗 | フルシンク実行 |

### リトライ仕様

ネットワークエラー時は自動リトライを行う。認証エラー時はトークン再取得後にリトライ。

## トランザクション仕様

同期処理はOperationQueueで逐次実行。複数の同期要求は一つにまとめられる。

## パフォーマンス要件

- 同期はバックグラウンドで非同期実行
- UIをブロックしない
- バッチ処理でメモリ使用量を制限

## セキュリティ考慮事項

- 通信はHTTPS経由で暗号化
- CSRFトークンによる認証
- トークンはSecureStorageに保存

## 備考

ReadingListsSyncOperationがOperation subclassとして実装され、バックグラウンドで実行される。

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

同期状態の管理構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ReadingListSyncState | `Wikipedia/Code/ReadingListsController.swift` | OptionSetで定義された同期状態フラグ |
| 1-2 | APIReadingList | `WMF Framework/ReadingListsAPIController.swift` | サーバーレスポンスのデータ構造 |
| 1-3 | APIReadingListEntry | `WMF Framework/ReadingListsAPIController.swift` | エントリのサーバーレスポンス構造 |

**読解のコツ**: ReadingListSyncStateはビットフラグで複数の状態を同時に表現。needsSync, needsUpdate, needsRemoteEnableなどの状態を組み合わせて使用。

#### Step 2: API通信を理解する

ReadingListsAPIControllerがサーバー通信の中心。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ReadingListsAPIController.swift | `WMF Framework/ReadingListsAPIController.swift` | API呼び出しの実装 |

**主要処理フロー**:
1. **132-134行目**: basePathComponentsでAPIパス定義
2. **137-153行目**: getメソッドでGETリクエスト
3. **155-187行目**: requestWithCSRFでCSRF認証付きリクエスト
4. **189-195行目**: postメソッド、deleteメソッド、putメソッド

#### Step 3: 同期オペレーションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ReadingListsSyncOperation.swift | `WMF Framework/ReadingListsSyncOperation.swift` | 同期処理の実装 |

**主要処理フロー**:
- ローカル未同期データの取得
- サーバーへのアップロード
- サーバーからのダウンロード
- Core Dataへのマージ

### プログラム呼び出し階層図

```
ReadingListsController
    │
    ├─ sync()
    │      └─ addOperation(ReadingListsSyncOperation)
    │
    └─ ReadingListsSyncOperation
           ├─ ReadingListsAPIController
           │      ├─ setup/teardown
           │      ├─ getAllReadingLists
           │      ├─ createReadingList
           │      ├─ updateReadingList
           │      ├─ deleteReadingList
           │      └─ addEntryToReadingList
           │
           └─ Core Data操作
                  ├─ 未同期データ取得
                  └─ サーバーデータ反映
```

### データフロー図

```
[ローカル]           [同期処理]              [サーバー]

Core Data ───▶ ReadingListsSyncOperation ◀──▶ Wikipedia API
                        │
                        ├─▶ 未同期データ抽出
                        ├─▶ サーバーへ送信
                        ├─▶ サーバーから受信
                        └─▶ Core Dataに反映
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ReadingListsController.swift | `Wikipedia/Code/` | ソース | 同期管理 |
| ReadingListsSyncOperation.swift | `WMF Framework/` | ソース | 同期処理Operation |
| ReadingListsAPIController.swift | `WMF Framework/` | ソース | API通信 |
| APIReadingListError | `WMF Framework/` | ソース | APIエラー定義 |
| Fetcher.swift | `WMF Framework/` | ソース | HTTP通信基盤 |
