Skip to content

feat(offline): 共通のストレージ世代判定・破棄ライフサイクルを追加 - #108

Merged
rdlabo merged 2 commits into
mainfrom
feat/offline-storage-generation
Oct 15, 2026
Merged

rdlabo merged 2 commits into
mainfrom
feat/offline-storage-generation

Conversation

@rdlabo

@rdlabo rdlabo commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

オフラインストレージの世代判定と破棄・再構築をkitへ共通化

SeatKeepとWinecodeで重複している、ローカルストレージの世代判定、破棄要求の永続化、再起動後の再構築を OfflineStorageLifecycle に集約します。アプリは世代・DB名・追加ファイルの削除・LiveUpdate準備待ちを設定します。

破棄は明示的なopt-inで、レプリカと未送信Outboxが対象です。認証情報は保持します。通信障害やサーバープロトコル不一致を破棄条件にしません。既存の世代・マーカー形式を引き継ぎます。

WebではWeb Locksで破棄と読み書きを排他制御し、世代変更前のランタイムによる操作を拒否します。既に配布済みの旧タブはこの仕組みに参加できないため、導入時の再読み込みが必要です。Winecodeの起動経路は軽量なstorage-generationエントリーポイントで遅延読み込みを維持します。

検証: 最終コードのkitオフライン全体662件、ライフサイクル13件、実Chromiumの2タブ検証、lint、SQLite並行処理・実DBテスト、全ライブラリビルド、packed package consumer検証が成功。SeatKeep250件および最終対象10件、Winecode26件、両アプリのCI設定ビルド成功。ネイティブ実機のアップデート経由の検証は未実施です。

上長・第三者受け入れレビュー: それぞれ独立したエージェントがkit ebbc500、SeatKeep b31f73267、Winecode af2548e71をレビューし、双方承認・差し戻しなし。第三者はライフサイクル13件と実Chromiumの2タブテストも再実行して成功。公開後にアプリの依存を公開版kitへ更新し、再検証します。

CI・Devin指摘への追補 (d6811cd): Angular21/TypeScript5.9のWeb Locks戻り値型に対応。DBなしでも追加cleanupが設定されている場合はreadinessを待って残存mediaを削除してから世代を確定。kit APIはreload失敗後の再呼出しで再試行可能。WinecodeのUIに自動再試行機能を追加するものではありません。回帰2件追加後、オフライン全体664件・lint成功。両レビュアーが再レビューし承認、差し戻しなし。

ブラウザー試験の範囲: localStorage adapterと実Web Locksの2タブ競合を検証。Ionic StorageのIndexedDBドライバーを含む統合試験は未実施です。

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 potential issues.

Devin Review

Comment on lines +115 to +119
if (!state.requested && options.rebuild === 'after-reload') {
if (await this.#hasStorage()) return 'reload-required';
await options.markerStore.set({ key: options.generationKey, value: state.generation });
this.#revision = (await options.markerStore.get({ key: this.#revisionKey })).value;
return 'ready';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 DB がない場合に古いメディアファイルが残る

after-reload で対象 DB だけが消えていると、新世代を確定して additionalCleanup を飛ばします。残ったメディアファイルは次回以降も破棄されません。

Learn more

after-reload の空ストレージ判定は、登録済み SQLite データベースの存在だけを検査します。additionalCleanup が管理するファイルは検査しません。DB の削除後にファイル削除が失敗した場合や、DB を持たずファイルだけ残る場合でも、新世代のマーカーを書いて以後の削除をスキップします。clearOfflineLocalDatabases でのみ追加クリーンアップが実行されます。

Example: 対象 DB が消えた後も写真ファイルが残っている初回起動で、rebuild: 'after-reload' を使うと prepare() は ready を返し、写真を残したまま世代を書き換えます。

Recommended fix: DB がない場合も additionalCleanup が管理する残存データの有無を判定できるようにするか、世代不一致時には安全な追加クリーンアップを実行してから完了マーカーを書いてください。

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +90 to +91
const state = await inspectOfflineStorageGeneration(this.options);
if (state.matches || state.requested) return false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 リセット要求の再試行で再起動が行われない

要求マーカーの保存後に再読み込みできなかった場合、再試行は false を返して再読み込みしません。そのランタイムはストレージを開けず、更新画面から復帰できません。

Learn more

この API は更新画面で準備完了を待ち、破棄要求を保存してからコールド再起動するためのものです。要求マーカーの書き込みと reload() の実行は別操作なので、再読み込みが失敗または中断されるとマーカーだけが残ります。再試行すると requested を検出して直ちに終了し、再読み込みできません。

Example: 1 回目に requested の保存は成功したが reload() が失敗した場合、2 回目は待機も再読み込みもせず false を返します。

Recommended fix: 既存の requested は破棄処理を重複実行する理由にはしない一方、呼び出し元のコールド再起動要求を妨げないようにしてください。複数の呼び出しが同時に走る場合の waitUntilReady と reload の順序も明示してください。

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +35 to +41
const storage = {
keys: async () => Object.keys(localStorage),
remove: async (key) => {
localStorage.setItem('deletions', String(Number(localStorage.getItem('deletions') ?? 0) + 1));
await new Promise((resolve) => setTimeout(resolve, 20));
localStorage.removeItem(key);
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 IndexedDB を使ったブラウザ統合検証は別途必要

2 タブのテストは localStorage アダプターを使います。Web Locks は検証できますが、Ionic Storage の IndexedDB ドライバーとの統合は検証できません。

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

@rdlabo
rdlabo merged commit 60bb699 into main Oct 15, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant