Skip to content

安装资源 转移至 chrome.storage.local 的 tempStorage. 代码部份放在 OPFS/temp_install_codes#1318

Open
cyfung1031 wants to merge 3 commits intorelease/v1.4from
pr/tempStorage-for-install
Open

安装资源 转移至 chrome.storage.local 的 tempStorage. 代码部份放在 OPFS/temp_install_codes#1318
cyfung1031 wants to merge 3 commits intorelease/v1.4from
pr/tempStorage-for-install

Conversation

@cyfung1031
Copy link
Copy Markdown
Collaborator

Checklist / 检查清单

  • Fixes mentioned issues / 修复已提及的问题
  • Code reviewed by human / 代码通过人工检查
  • Changes tested / 已完成测试

Description / 描述

Screenshots / 截图

@CodFrm
Copy link
Copy Markdown
Member

CodFrm commented Mar 28, 2026

👀 要大规模的用起 OPFS 来了吗,先不急着处理这个问题,留下一个版本去,v1.4准备做重构UI这件大事

@cyfung1031
Copy link
Copy Markdown
Collaborator Author

👀 要大规模的用起 OPFS 来了吗,先不急着处理这个问题,留下一个版本去,v1.4准备做重构UI这件大事

先合并吧
不然UI改了又合不到

@CodFrm
Copy link
Copy Markdown
Member

CodFrm commented Mar 28, 2026

👀 要大规模的用起 OPFS 来了吗,先不急着处理这个问题,留下一个版本去,v1.4准备做重构UI这件大事

先合并吧 不然UI改了又合不到

可以

return cacheInstance.get<[boolean, ScriptInfo]>(cacheKey);
async getInstallInfo(uuid: string) {
const entry = await new TempStorageDAO().get(uuid);
cleanupStaleTempStorageEntries();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

每次调用都会启动cleanupStaleTempStorageEntries,而且内部逻辑复杂;我觉得做一个定时任务,每隔多久,扫描一次全部的,清理一下就可以了

}
info = createScriptInfo(uuidv4(), code, `file:///*from-local*/${file.name}`, "user", metadata);
const uuid = uuidv4();
info = await createScriptInfoLocal(uuid, code, `file:///*from-local*/${file.name}`, "user", metadata);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

把uuid拆开的意义何在

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

本 PR 旨在将“安装页临时安装信息/脚本代码”的存储从原先的 session cache 迁移:元信息转存到 chrome.storage.localtempStorage,脚本代码主体转存到 OPFS 的 temp_install_codes,以降低 session storage 压力并便于跨页面/重启场景取回安装数据。

Changes:

  • 新增 TempStorageDAOchrome.storage.local)用于保存安装临时条目(不含代码正文)。
  • 新增 OPFS 目录 temp_install_codes 存取/清理临时代码,并在安装页通过 uuid 回读代码。
  • Service Worker 与安装页流程改为读写 tempStorage + OPFS,并新增 stale 清理逻辑入口。

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/pkg/utils/scriptInstall.ts 增加 OPFS 临时代码写入/读取/删除与构造 temp entry 的工具方法
src/pages/install/App.tsx 安装页改为从 TempStorage + OPFS 组装安装信息,并新增 keep-alive 机制
src/app/service/service_worker/temp.ts 新增 SW 侧 stale 临时条目清理逻辑
src/app/service/service_worker/subscribe.ts 订阅更新触发安装页前改为写入 TempStorage + OPFS
src/app/service/service_worker/script.ts getInstallInfo 与打开安装页流程改为读取/写入 TempStorage + OPFS,并触发清理
src/app/repo/tempStorage.ts 新增 TempStorageDAO(Repo 前缀 tempStorage:)与 staleEntries 逻辑
src/app/cache_key.ts 移除不再使用的 CACHE_KEY_SCRIPT_INFO 常量

const list = stales.map((e) => e.key);
const list1 = stales.filter((entry) => entry.type === TempStorageItemType.tempCode).map((e) => e.key);
await removeCachedCodes(list1);
cacheInstance.dels(list);
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

这里清理 stale TempStorage 条目时使用了 cacheInstance.dels(list),但 cacheInstancechrome.storage.session(见 src/app/cache.ts),而 TempStorageDAO 数据实际保存在 chrome.storage.localRepo 基类)。这会导致 tempStorage 条目永远不会被删除,长时间运行会持续堆积。建议改为调用 new TempStorageDAO().deletes(list)(或等价的 delete API)来删除 tempStorage: 前缀下的记录。

Suggested change
cacheInstance.dels(list);
await new TempStorageDAO().deletes(list);

Copilot uses AI. Check for mistakes.
throw new Error("fetch script info failed");
}
const code = await getTempCode(uuid);
if (code) info.code = code;
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

这里从 OPFS 读取安装代码后仅在 code 为 truthy 时才写回 info.code。但 getTempCode() 在任何异常都会返回空字符串,导致后续 prepareScriptByCode/prepareSubscribeByCode 直接拿到空代码并出现难以定位的错误/空白安装页。建议在 uuid 场景下把“读不到代码”视为错误(例如空字符串就抛错/提示用户),或让 getTempCode 返回 undefined/抛出以便区分“文件不存在/读取失败”和“代码为空”。

Suggested change
if (code) info.code = code;
// 这里从 OPFS 读不到代码(getTempCode 返回空字符串)应视为错误,避免后续拿到空代码导致空白安装页
if (code === "") {
throw new Error("failed to load script code from temp storage");
}
if (code) {
info.code = code;
}

Copilot uses AI. Check for mistakes.
Comment on lines +37 to +43
export const getTempCode = async (tempUUID: string): Promise<string> => {
try {
const folder = await navigator.storage.getDirectory().then((root) => root.getDirectoryHandle("temp_install_codes"));
const handle = await folder.getFileHandle(`${tempUUID}.user.js`);
return await handle.getFile().then((f) => f.text());
} catch {
return "";
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

getTempCode 捕获所有异常并返回空字符串,会把“读取失败/文件不存在”和“代码确实为空”混在一起,调用方很难做可靠的错误处理(目前 install 页也因此可能继续用空代码往下走)。建议改为返回 undefined(文件不存在/读取失败)或直接抛出异常,并在调用处统一提示;如果一定要吞错,至少区分 NotFound 与其它异常并打日志以便排障。

Suggested change
export const getTempCode = async (tempUUID: string): Promise<string> => {
try {
const folder = await navigator.storage.getDirectory().then((root) => root.getDirectoryHandle("temp_install_codes"));
const handle = await folder.getFileHandle(`${tempUUID}.user.js`);
return await handle.getFile().then((f) => f.text());
} catch {
return "";
export const getTempCode = async (tempUUID: string): Promise<string | undefined> => {
try {
const folder = await navigator.storage
.getDirectory()
.then((root) => root.getDirectoryHandle("temp_install_codes"));
const handle = await folder.getFileHandle(`${tempUUID}.user.js`);
return await handle.getFile().then((f) => f.text());
} catch (err: any) {
// 文件不存在时返回 undefined,其它异常打日志并抛出,方便上层统一处理
if (err && (err.name === "NotFoundError" || err.code === "NotFoundError")) {
return undefined;
}
console.error("[scriptInstall] Failed to read temp install code", err);
throw err;

Copilot uses AI. Check for mistakes.
- 修复清理时 cacheInstance.dels 删错存储位置(session→local)
- cleanup 改为 chrome.alarms 定时任务,移除 getInstallInfo 副作用
- 安装页 keepAlive 直接更新 TempStorageDAO.savedAt,移除 keepTemp 中转
- getTempCode 区分 NotFoundError 与其他异常,调用方对空代码抛错
- staleEntries 使用 this 替代多余的 new 实例
@CodFrm
Copy link
Copy Markdown
Member

CodFrm commented Mar 29, 2026

Code Review 修复

已提交修复 509bb2c1,主要改动:

  1. 🐛 修复清理删错存储位置cacheInstance.dels(list) 删的是 session storage,但 TempStorageDAO 数据在 local storage,导致条目永远不会被清除。改为 new TempStorageDAO().deletes(list)
  2. 🔧 cleanup 改为 chrome.alarms 定时任务 — 从 getInstallInfo 中移除副作用调用,改为 SW 中 chrome.alarms 每 30 分钟执行一次
  3. 🔧 移除 keepTemp 中转 — 安装页 startKeepAlive 直接更新 TempStorageDAO.savedAt,cleanup 只看 savedAt 即可判断是否过期,不再需要 session cache 中转
  4. 🔧 getTempCode 错误处理 — 区分 NotFoundError(返回 undefined)与其他异常(throw),调用方对读不到代码的场景抛错提示
  5. 🔧 staleEntries 修复new TempStorageDAO()this

@cyfung1031
Copy link
Copy Markdown
Collaborator Author

cyfung1031 commented Mar 29, 2026

@CodFrm 你把 cleanupStaleTempStorageEntries 改成只检查 savedAt ... 我要再看看

本来的设计是检查session
不过只用时间值检查应该也可以

@cyfung1031 cyfung1031 marked this pull request as draft March 29, 2026 21:57
@cyfung1031
Copy link
Copy Markdown
Collaborator Author

好吧应该没什么问题。
就这样

@cyfung1031 cyfung1031 marked this pull request as ready for review March 29, 2026 22:02
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.

CACHE_KEY_SCRIPT_INFO (安装页面用的) scriptInfo (短期)储存优化

3 participants