@zhushanwen/pi-scheduler 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/src/runtime.ts +30 -31
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhushanwen/pi-scheduler",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"xyz-agent": {
|
|
@@ -46,7 +46,8 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@xyz-agent/session-delivery": "0.3.1",
|
|
49
|
-
"@zhushanwen/pi-
|
|
49
|
+
"@zhushanwen/pi-ext-guards": "0.3.0",
|
|
50
|
+
"@zhushanwen/pi-extension-logger": "0.6.0"
|
|
50
51
|
},
|
|
51
52
|
"scripts": {
|
|
52
53
|
"test": "vitest run",
|
package/src/runtime.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ExtensionContext } from '@earendil-works/pi-coding-agent'
|
|
2
|
+
import { guardStaleCtx, toErrorMessage } from '@zhushanwen/pi-ext-guards'
|
|
2
3
|
import { getLogger } from '@zhushanwen/pi-extension-logger'
|
|
3
4
|
|
|
4
5
|
import type { DeliveryHandle, DeliveryMessage } from '@xyz-agent/session-delivery'
|
|
@@ -25,16 +26,13 @@ const TICK_INTERVAL_MS = 30_000
|
|
|
25
26
|
const DEFAULT_EXPIRY_DAYS = 7
|
|
26
27
|
const DEFAULT_EXPIRY_MS = DEFAULT_EXPIRY_DAYS * MS_PER_DAY // 7 days
|
|
27
28
|
const HISTORY_LIMIT = 20 // 与 replayFoldEntries 的裁剪上限一致(advance 折叠 / dispatch 累积共用)
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
// 注意:pi 非契约 API(Error message 非稳定接口),pi 升级需回归验证 runtime.test.ts 的
|
|
36
|
-
// U1 / G1-d 文案锚定用例;文案变更时此兜底失效,后果为 timer 泄漏 + 每 30s warn(不 crash)。
|
|
37
|
-
const STALE_CTX_MARKER = 'stale after session replacement'
|
|
29
|
+
// STALE_CTX_MARKER(文案兜底分诊词)已迁移到 ext-guards 共享守卫(guardStaleCtx 内部
|
|
30
|
+
// 引用,本文件不再直接持有)。语义:G1 模块级代际检测(isCtxStale)为主判;文案子串
|
|
31
|
+
// 覆盖代际盲区——显式 reload / cwd 变化触发 clearExtensionCache 后 jiti 重新 import 产生
|
|
32
|
+
// 全新模块环境,旧闭包引用的模块级代数冻结不再递增,isCtxStale 恒 false,只剩错误文案
|
|
33
|
+
// 能识别 stale。pi 非契约 API(Error message 非稳定接口):文案由 docs/pi-semantics.json
|
|
34
|
+
// PS-30 探针随 pi 版本门禁自动重验;pi 升级仍需回归 runtime.test.ts 的 U1 / G1-d 文案
|
|
35
|
+
// 锚定用例。文案变更时此兜底失效,后果为 timer 泄漏 + 每 30s warn(不 crash)。
|
|
38
36
|
|
|
39
37
|
export class SchedulerRuntime {
|
|
40
38
|
private tasks: Map<string, ScheduledTask> = new Map()
|
|
@@ -201,27 +199,28 @@ export class SchedulerRuntime {
|
|
|
201
199
|
startScheduler(): void {
|
|
202
200
|
if (this.tickTimer) return
|
|
203
201
|
this.tickTimer = setInterval(() => {
|
|
204
|
-
//
|
|
205
|
-
//
|
|
206
|
-
//
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
//
|
|
213
|
-
//
|
|
214
|
-
//
|
|
215
|
-
//
|
|
216
|
-
//
|
|
217
|
-
//
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
202
|
+
// 三件套语义等价迁移到共享守卫 guardStaleCtx(crash-resilience D1 / u1-ext-guard;
|
|
203
|
+
// 守卫语义 = 本处原地实现的泛化,迁移对照逐条可证):
|
|
204
|
+
// 1. G1 前置检查(S9):守卫的 isCtxStale 命中 → onStale(= retireStaleTimer)且
|
|
205
|
+
// tickScheduler 不执行——与迁移前「前置分支 return」等价:本 runtime 所属 session
|
|
206
|
+
// 已被替换 → timer 属泄漏资源自停退场,不触碰捕获的 stale ctx,不依赖 pi 错误文案。
|
|
207
|
+
// 主防线仍是 F1(session_start 停旧 timer),此处覆盖 F1 未能触达的泄漏路径。
|
|
208
|
+
// 2. F2 catch 分诊(防御兜底):守卫对 tickScheduler 的 rejection 挂同一分诊谓词
|
|
209
|
+
// `isCtxStale() || 文案含 STALE_CTX_MARKER`(字面不变)——stale → retireStaleTimer;
|
|
210
|
+
// 非 stale → 原样 reject,由下方 .catch 仅告警不终止调度('tick error' 文案不变,
|
|
211
|
+
// U2/G1-c 锚定)。fire-and-forget 的 tick 链路必须自带 catch——tick 内任何异常
|
|
212
|
+
// (典型:泄漏 timer 的 onAfterTick → refreshWidget 访问 stale ctx.ui 抛错)无人接住
|
|
213
|
+
// 即 unhandledRejection,直接崩掉 pi 主进程(E1 同机制)。
|
|
214
|
+
// 3. retireStaleTimer 自停:未改('tick stopped' warn 口径与幂等 stopScheduler 原样,
|
|
215
|
+
// U1/G1-b/G1-d 锚定)。
|
|
216
|
+
// `?.catch`:前置检查命中时守卫返回 undefined(fn 未执行、无 Promise、无 rejection
|
|
217
|
+
// 可接——retire 已由 onStale 完成);非 stale 时返回 Promise,非 stale rejection
|
|
218
|
+
// 流到 .catch 仅告警。
|
|
219
|
+
void guardStaleCtx(() => this.tickScheduler(), {
|
|
220
|
+
isCtxStale: this.isCtxStale,
|
|
221
|
+
onStale: () => this.retireStaleTimer(),
|
|
222
|
+
})?.catch((err: unknown) => {
|
|
223
|
+
logger.warn('tick error', { error: toErrorMessage(err) })
|
|
225
224
|
})
|
|
226
225
|
}, TICK_INTERVAL_MS)
|
|
227
226
|
}
|