Skip to content

[DRAFT] ♻️ GM value 更新流程重构:storageName 分组批处理、顺序一致与 updatetime 严格递增 (#1125 重设计)#1627

Draft
cyfung1031 wants to merge 1 commit into
scriptscat:mainfrom
cyfung1031:claude/pr-redesign-submission-ce1571
Draft

[DRAFT] ♻️ GM value 更新流程重构:storageName 分组批处理、顺序一致与 updatetime 严格递增 (#1125 重设计)#1627
cyfung1031 wants to merge 1 commit into
scriptscat:mainfrom
cyfung1031:claude/pr-redesign-submission-ce1571

Conversation

@cyfung1031

@cyfung1031 cyfung1031 commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Checklist / 检查清单

  • Fixes mentioned issues / 修复已提及的问题: 最终写入顺序可能与调用顺序不一致
  • Code reviewed by human / 代码通过人工检查
  • Changes tested / 已完成测试

N/A — 「Fixes mentioned issues」:本 PR 为优化/重构,无对应 issue。

背景

#1125 的想法在最新 main 上重新设计实现(#1125 基于旧架构、已关闭;其部分内容如 GM_deleteValue link 修正、verify<T> 泛型、aNow 工具已在 main 落地,不再重复)。目前 main 的 GM value 流程仍存在:

  1. 并发 setValues 顺序可被打乱setValues 在进入 per-storage 队列前先 await scriptDAO.get(uuid),多个并发调用的入队次序取决于该异步读取的耗时,最终写入顺序可能与调用顺序不一致。
  2. 同一 storageName 的连续更新逐条读写/推送:每次 setValues 都各自 valueDAO.get + save + 推送一次,高频写入时浪费明显。
  3. updatetime 不更新且不保证递增:现有实现只在 value 模型创建时写入 updatetime,后续变更从不更新;同一时间片内的连续更新也无法区分先后。
  4. 各页面 valueStore 的 key 顺序可能不一致:本地乐观写入与 SW 下发更新的到达顺序不同,导致 GM_listValues 等遍历顺序在不同页面间发散(优先度:低)。
  5. valueChangeListener 同步执行:监听器回调在更新循环内同步执行,可能阻塞/干扰 valueStore 的同步更新流程。

本次改动

对脚本用户可见的行为不变(GM value API 语义不变),内部流程调整:

  • ValueService.setValues 两级队列化src/app/service/service_worker/value.ts):
    • 全局 valueChangeOnSequence 顺序队列保证任务入队次序与调用次序一致;
    • 任务以 storageName 分组累积,由 setValuesByStorageName 在 per-storage 队列(沿用 CACHE_KEY_SET_VALUE 锁)中集中处理:一次 valueDAO.get、按序应用全部任务、至多一次 save、一次推送。
  • updatetimeaNow() 写入:值实际变更时更新 updatetime,同一时间片内亦严格递增;创建路径保留原有 ts 回填语义。
  • 推送结构瘦身归一src/app/service/content/types.ts):新增 ValueUpdateSendData = { storageName, storageChanges: Record<uuid, ValueUpdateDataEncoded[]> }ValueUpdateDataEncodedentries 更名 valueChanges、移除可由 valueChanges.length 推导的 valueUpdated 字段。RuntimeService.pushValueUpdate 改收 updatedScripts: Script[](本批实际变更的脚本,用于 early-start 重注册)+ 一份 ValueUpdateSendData
  • 接收端适配scripting.ts / script_runtime.ts / script_executor.ts / sandbox runtime.ts 按新结构分发;匹配逻辑(uuid / storageName)收敛到 ExecScript.valueUpdate。sandbox 侧 crontab 脚本的 value 同步顺带修正了 undefined 应删除 key 而非写入 undefined 的问题。
  • content GM Apigm_api.ts):
    • valueUpdate 改为 valueStoreUpdate(valueStore, responses),同步更新 store;valueChangeListener 回调延后到下一个 microTask 执行;
    • 引入 extValueStoreCopy:以 SW 确认顺序维护 store 快照,SW 更新到达时以快照为基准应用,使各页面 key 顺序一致;
    • 抽出 generateValChangeId() 消除 _GM_setValue / _GM_setValues 的重复计数器逻辑。
  • 死代码清理(同一子系统内):删除已无发布/订阅方的 MQ 类型 TScriptValueUpdate(旧 valueUpdate MQ 事件在 storage.session 广播改造时已移除)与未被引用的 ValueUpdateData / ValueUpdateDataEntry 类型。

实现考虑

  • 批次取走的原子性setValuesByStorageName 在任何 await 之前同步取走并删除该 storageName 的整批任务表,之后入队的任务会建立新列表并由其自己的队列调用处理,不存在丢任务窗口。
  • 无变更也推送:客户端 GM.setValue 等依赖带 id 的回执解除等待,因此即使本批无实际变更也照常推送(valueChanges 为空数组)。
  • early-start 处理updatedScripts 按 uuid 去重,仅对本批有实际变更、启用中且为 early-start 的脚本执行 updateResourceOnScriptChange,语义与原实现一致。
  • extValueStoreCopy 的取舍:本地乐观写入不进快照;未被 SW 确认的本地写入在下一次 SW 更新到达时会暂时回退、待确认后恢复 —— 以此换取跨页面 key 顺序一致(与 [Dev] GM value 代码相关调整优化 - 包括 确保 script.value key 顺序跨页一致(优先度:低) (PR-TAG: TBC) #1125 设计一致,优先度低,可单独讨论)。

建议审查重点

  • setValuesByStorageName 的批处理边界:批内多 uuid(共享 storageName)、isReplace、新建 value 模型 + ts 回填路径。
  • 监听器回调延后一个 microTask 是否影响依赖同步回调时序的既有脚本场景。
  • extValueStoreCopy 的乐观写入回退窗口是否可接受。

关联

验证

  • pnpm test:309 文件 / 3436 测试全部通过。
  • pnpm lint:prettier + tsc + check:i18n + eslint 全部通过。
  • TDD:先按新契约改写 value.test.ts(新增批处理合并、顺序一致、updatetime 严格递增、错误不卡队列等用例,7 例先失败)再实现;gm_api.test.ts / create_context.test.ts 适配新签名并补充监听器 microTask 延后断言。

🤖 Generated with Claude Code

@cyfung1031 cyfung1031 changed the title ♻️ GM value 更新流程重构:storageName 分组批处理、顺序一致与 updatetime 严格递增 [DRAFT] ♻️ GM value 更新流程重构:storageName 分组批处理、顺序一致与 updatetime 严格递增 Jul 20, 2026
@cyfung1031 cyfung1031 changed the title [DRAFT] ♻️ GM value 更新流程重构:storageName 分组批处理、顺序一致与 updatetime 严格递增 [DRAFT] ♻️ GM value 更新流程重构:storageName 分组批处理、顺序一致与 updatetime 严格递增 (#1125 重设计) Jul 20, 2026
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