Meilisearch 更新タイミング一覧
subtitles インデックスの各フィールドについて、「いつ、何がきっかけで更新されるか」 をまとめる。
Meilisearch は 字幕本文の保存先 であると同時に 検索インデックス として機能する(データベース概要 参照)。本文自体は Turso には存在しないため、復旧は YouTube からの再取得に頼る。ただし冗長保存されているメタフィールド(channelCountry / subscriberCount 等)は Turso 側の変動に連動して partial update される。
Turso 側の更新タイミングは Turso 更新タイミング を参照。トリガー番号(T1〜T12)は両ページ共通で、両系統にまたがるトリガーは両方から参照される。
詳細なフィールド定義は Meilisearch インデックススキーマ を参照。
1. Turso からの伝播
Meilisearch への書き込みは 全て Turso 側のイベントが起点 になる(直接 Meilisearch に対して手動で書き換える運用は想定していない)。Meilisearch を書き換えるのは以下の 4 トリガー。
| # | トリガー | 実装 | Meilisearch への操作 |
|---|---|---|---|
| T6 | チャンネル初回取り込み | startChannelFirstFetch → enqueueChannelFetch → SUBTITLE_FETCH_QUEUE → Queue Consumer (queue-handlers/subtitle-fetch-handler) | チャンネル配下の動画 ID を Cloudflare Queue に投入し、Consumer Worker が動画ごとに字幕を取得して segment ドキュメントを INSERT。進捗は SubtitleFetchProgressDO で追跡(#328) |
| T7 | チャンネル 24h 差分取得(#305) | fetchChannelDiff → enqueueChannelFetch → SUBTITLE_FETCH_QUEUE → 上記 Consumer | 新規動画分の segment を INSERT。さらに channels.country / channels.subscriber_count(#84 以降)が変動した場合、同チャンネルの全 subtitle document を updateDocuments(partial update)で追従 |
| T8 | 字幕取得ジョブ完了 | Queue Consumer (subtitle-fetch-handler) | 動画 1 本の字幕 segment を addDocuments で投入し、SubtitleFetchProgressDO の recordCompleted をコール |
| T12 | DMCA テイクダウン | 管理者操作 | 該当動画の全 subtitle document を削除 |
Meilisearch には updateDocuments による partial update(指定フィールドのみ更新、他フィールドは保持)があるため、channelCountry だけ、subscriberCount だけ、といった最小差分の反映ができる。本文 text を誤って上書きしない。
2. フィールド別: どのトリガーで更新されるか
Meilisearch の subtitles インデックス 1 ドキュメント = 字幕の 1 セグメント。全フィールドは Turso から供給される。
| フィールド | 初回投入タイミング | 更新トリガー | 備考 |
|---|---|---|---|
id | T8 | 不変 | {videoId}_{segmentIndex} 形式の primary key |
videoId / channelId | T8 | 不変 | 動画・チャンネルの参照 |
text | T8 | 更新されない | 字幕本文。YouTube 側で変更されても再取得しない限り反映しない |
startTime / endTime / language | T8 | 不変 | セグメントの時刻と言語 |
title | T8 | 動画タイトル変更への追従は未実装 | Turso の videos.title が更新されないため |
publishedAt | T8 | 不変 | videos.published_at を Unix 秒に変換 |
viewCount / likeCount | T8(DB 値をコピー) | 事実上不変 | Turso 側の videos.view_count / like_count が初回取得時のみ設定のため(#84 のソート機能で課題になる) |
categoryId | T8 | 不変 | videos.category_id |
channelCountry | T8(channels.country をコピー) | T7 で channels.country 変動時、対象チャンネルの全ドキュメントを partial update | #305 以降 |
durationSeconds(#84 で追加予定) | T8(videos.duration_seconds をコピー) | 不変 | 動画の長さは変動しない |
subscriberCount(#84 で追加予定) | T8(channels.subscriber_count をコピー) | T7 で channels.subscriber_count 変動時、対象チャンネルの全ドキュメントを partial update(変動なしならスキップ) | 追加クォータコストなし |
3. 削除トリガー
| # | トリガー | 操作 |
|---|---|---|
| T12 | DMCA テイクダウン | 該当 videoId を含む全 subtitle document を deleteDocuments で削除 |
| - | 将来構想 | videos.subtitle_status = 'deleted' のレコードを月次バッチでクリーンアップ(未実装) |
4. 冗長保存フィールドの同期チェーン(Meilisearch 視点)
Turso 側の 1 箇所を変更したときに、Meilisearch が何を受け取るか。
チェーン A: チャンネルメタデータ変更(T7)
Turso: fetchChannelDiff で channels を UPSERT
↓
Meilisearch: 該当チャンネルの全 subtitle document に対して
├─ [country 変動時] channelCountry を updateDocuments で partial update
└─ [subscriber_count 変動時 / #84 以降] subscriberCount を partial update
(変動なしのフィールドはスキップ。他フィールドは保持)
チェーン E: 字幕取得完了(T8)
Turso: videos.subtitle_status = 'completed' に遷移
↓
Meilisearch: 当該動画の字幕セグメントを addDocuments で投入
(1 動画 = 数十〜数百セグメント)
チェーン F: DMCA 削除(T12)
管理者操作
├─ Turso: videos.subtitle_status = 'deleted' に遷移
└─ Meilisearch: videoId = X の全ドキュメントを deleteDocuments で削除
5. 「更新されないが、更新すべきか議論中」の項目(Meilisearch 関連)
| 項目 | 現状 | 懸念 | 対応状況 |
|---|---|---|---|
viewCount / likeCount(document 上) | Turso と同期。Turso 側が初回取得のみのため実質不変 | ソートすると「1 年前の値」で並ぶ | #84 のスコープ外。別 Issue で動画単位更新戦略と同時に議論 |
title(document 上) | T8 時のコピー | YouTube 側でオーナーが変更しても追従しない | 必要性が顕在化したら別 Issue |
字幕本文 (text) の復旧 | 唯一の保存先なので復旧は YouTube 再取得に依存 | Meilisearch のデータ損失 = 全チャンネル再取得(YouTube Data API のクォータ制約大) | Meilisearch VM の Docker ボリュームスナップショット運用を検討中 |
関連資料
- Meilisearch インデックススキーマ — フィールド定義・searchable / filterable / sortable 属性
- Meilisearch セットアップ手順 — VM / Docker / API キーの運用
- Turso 更新タイミング — DB 側のトリガー詳細
- データ戦略 — 字幕取得フローの全体設計