实现 WakeUpPing#1347
Conversation
|
直接全局的ping吗?这样是不是不太好,我觉得在gm xhr中ping就好了 |
|
不是单一解决 |
我明白,不过MV3闲置时关闭SW本身就没问题 |
当然这个设计最终也有可能被Chrome砍掉吧。毕竟Chrome就是不想搞长驻 |
也可以接受,就是又是一个架构层面的变更,很担心影响面,留到下个版本吧,准备发布v1.4的正式版本了 |
|
好像有规管风险。我先处理一下 |
改了只在 xhr 执行时启动 当 GM xhr 执行时,会延时进行ping,然后如果 GM xhr 未结束,就会再延时进行ping,一直重复 |
There was a problem hiding this comment.
Pull request overview
该 PR 为了解决 #1343 中「长时间 XHR 导致 Service Worker 休眠后无法收到响应」的问题,引入 offscreen→service worker 的定时唤醒机制(WakeUpPing),并在 GM_xmlhttpRequest 执行期间启停该机制,以降低长请求期间 SW 被回收的概率。
Changes:
- 新增
wakeup-ping工具:offscreen 侧周期性 ping,SW 侧通过写入 session storage 触发活动。 - service worker 启动时注册 WakeUpPing 监听,用于调试/观察唤醒信号。
GM_xmlhttpRequest开始/结束时发送 START/STOP 指令控制 offscreen ping。
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| src/service_worker.ts | 注册 WakeUpPing 监听,并增加调试用的 onWakeupPing 回调 |
| src/pkg/utils/wakeup-ping.ts | 新增 WakeUpPing 实现:BroadcastChannel +(拟)storage 事件触发 |
| src/offscreen.ts | offscreen 启动时初始化 WakeUpPing(等待 SW 指令后开始 ping) |
| src/app/service/service_worker/gm_api/gm_api.ts | GM_xmlhttpRequest 生命周期内发送 START/STOP 控制唤醒 |
| export const listenWakeupPing = (onWakeupPing: (...args: any) => any) => { | ||
| chrome.storage.session.onChanged.addListener((obj) => { | ||
| // 消耗 persistentWakeup | ||
| if (typeof obj.persistentWakeup !== "undefined") { | ||
| // 执行任意 callback | ||
| onWakeupPing(); | ||
| } | ||
| }); | ||
| channel.onmessage = (e) => { | ||
| // 触发 chrome storage onChanged 使 service worker 保持活跃 | ||
| chrome.storage.session.set({ persistentWakeup: `${e.timeStamp}` }); | ||
| }; | ||
| }; |
| // https://github.com/scriptscat/scriptcat/issues/1343 | ||
| let wakeupTrigger = true; | ||
| wakeupPingCommand(WakeUpCommand.START); | ||
| const wakeupStop = () => { | ||
| try { | ||
| if (wakeupTrigger) { | ||
| wakeupTrigger = false; | ||
| wakeupPingCommand(WakeUpCommand.STOP); | ||
| } | ||
| } catch { | ||
| // ignored | ||
| } | ||
| }; | ||
|
|
||
| const msgConn = sender.getConnect()!; | ||
|
|
||
| let isConnDisconnected = false; | ||
| msgConn.onDisconnect(() => { | ||
| isConnDisconnected = true; | ||
| wakeupStop(); | ||
| }); |
| // initializeWakeupPing only execute once in offscreen | ||
| export const initializeWakeupPing = () => { | ||
| if (typeof frameElement === "object" && typeof document === "object" && document) { | ||
| let counter = 0; | ||
| let isMutationPending = false; | ||
|
|
||
| const pingNode = document.createComment("0"); | ||
|
|
||
| const incrementCounter = () => { | ||
| if (startCounter >= 1 && !isMutationPending) { | ||
| isMutationPending = true; | ||
| counter = counter & 8 ? 1 : counter + 1; | ||
| pingNode.data = `${counter}`; | ||
| } | ||
| }; | ||
|
|
||
| const pingTask = async () => { | ||
| channel.postMessage(true); | ||
| incrementCounter(); | ||
| }; | ||
|
|
||
| const mutationObserver = new MutationObserver(() => { | ||
| if (isMutationPending) { | ||
| isMutationPending = false; | ||
| const pingIntervalMs = Math.random() * (PING_INTERVAL_MS_2 - PING_INTERVAL_MS_1) + PING_INTERVAL_MS_1; | ||
| if (nativeScheduler) { | ||
| nativeScheduler.postTask(pingTask, { priority: "background", delay: pingIntervalMs }); | ||
| } else { | ||
| setTimeout(pingTask, pingIntervalMs); | ||
| } | ||
| } | ||
| }); | ||
| mutationObserver.observe(pingNode, { characterData: true }); | ||
| // incrementCounter(); | ||
|
|
||
| channelCommand.onmessage = (e) => { | ||
| if (e.data === WakeUpCommand.START) { | ||
| startCounter++; | ||
| if (startCounter === 1) { | ||
| incrementCounter(); | ||
| } | ||
| } else if (e.data === WakeUpCommand.STOP) { | ||
| if (startCounter > 0) startCounter--; | ||
| } | ||
| }; | ||
| } | ||
| }; | ||
|
|
||
| // initializeWakeupPing only execute once in service worker | ||
| export const listenWakeupPing = (onWakeupPing: (...args: any) => any) => { | ||
| chrome.storage.session.onChanged.addListener((obj) => { | ||
| // 消耗 persistentWakeup | ||
| if (typeof obj.persistentWakeup !== "undefined") { | ||
| // 执行任意 callback | ||
| onWakeupPing(); | ||
| } | ||
| }); | ||
| channel.onmessage = (e) => { | ||
| // 触发 chrome storage onChanged 使 service worker 保持活跃 | ||
| chrome.storage.session.set({ persistentWakeup: `${e.timeStamp}` }); | ||
| }; | ||
| }; | ||
|
|
||
| // wakeupPingCommand only execute in service worker | ||
| export const wakeupPingCommand = (command: WakeUpCommand) => { | ||
| channelCommand.postMessage(command); | ||
| }; |
Code reviewFound 4 issues:
scriptcat/src/pkg/utils/wakeup-ping.ts Lines 72 to 80 in 76abf19
At line 818, scriptcat/src/app/service/service_worker/gm_api/gm_api.ts Lines 805 to 818 in 76abf19
A debug-only assignment ( scriptcat/src/service_worker.ts Lines 63 to 66 in 76abf19
Three comments in the new scriptcat/src/pkg/utils/wakeup-ping.ts Lines 24 to 87 in 76abf19 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
|
我也只是一想,还没验证这个方案是否有效,我弄了一个脚本和网站,我试试 |
主要是我无法重现 #1343 的问题 |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Checklist / 检查清单
Description / 描述
隔一段时间从 offscreen ping一下,防止 service worker 休眠
Screenshots / 截图