From a1fe2dcbf415ff393a39fa238cf219158b2da4bd Mon Sep 17 00:00:00 2001 From: wangwangit Date: Sun, 24 May 2026 19:13:06 +0800 Subject: [PATCH] =?UTF-8?q?fix(scheduler):=20NOTIFICATION=5FHOURS=20?= =?UTF-8?q?=E9=80=9A=E9=85=8D=E7=AC=A6=20"*"=20=E8=A2=AB=20padStart=20?= =?UTF-8?q?=E8=AF=AF=E5=A4=84=E7=90=86=E4=B8=BA=20"0*"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 本地 wrangler dev 测试时发现:用户配置 "*" 后,inWindow 始终判定 false, 反而比 v2 不能用。 根因:v3 scheduler 对配置数组无脑 padStart(2,'0'),把 '*' 变成 '0*'。 修复 src/services/scheduler.js:normalize 时仅对纯数字 padStart; '*' / 'ALL' 保持原样。 测试 tests/services/scheduler.test.js:新增 "场景5:通配符不应被 padStart" 确保回归。 171 测试全绿。 发现自我们 @ 2026-05-24 19:11 在本地 dev 环境实测中。 --- src/services/scheduler.js | 10 +++++++++- tests/services/scheduler.test.js | 29 +++++++++++++++++++++++++++++ wrangler.dev.toml | 27 +++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 wrangler.dev.toml diff --git a/src/services/scheduler.js b/src/services/scheduler.js index 131ee09..b03d649 100644 --- a/src/services/scheduler.js +++ b/src/services/scheduler.js @@ -60,7 +60,15 @@ export async function checkExpiringSubscriptions(env) { const now = getNowInTimezone(timezone); const normalizedHours = Array.isArray(config.NOTIFICATION_HOURS) - ? config.NOTIFICATION_HOURS.map((h) => String(h).padStart(2, '0')) + ? config.NOTIFICATION_HOURS + .map((h) => String(h).trim()) + .filter((h) => h.length > 0) + .map((h) => { + const up = h.toUpperCase(); + if (up === '*' || up === 'ALL') return '*'; + // 仅对纯数字做两位补齐;'*' 之类通配符保持原样 + return /^\d+$/.test(h) ? h.padStart(2, '0') : up; + }) : []; const inWindow = normalizedHours.length === 0 || diff --git a/tests/services/scheduler.test.js b/tests/services/scheduler.test.js index 0486942..0cee2fc 100644 --- a/tests/services/scheduler.test.js +++ b/tests/services/scheduler.test.js @@ -193,6 +193,35 @@ describe('scheduler v3 - 时区 + 通知时段', () => { expect(fetchSpy).toHaveBeenCalledTimes(1); // 只发了一次 }); + + it('场景5:NOTIFICATION_HOURS=["*"] 通配符不应被 padStart 误处理为 "0*"', async () => { + vi.useFakeTimers(); + vi.setSystemTime(new Date('2026-05-24T00:00:00.000Z')); + await setConfig({ + JWT_SECRET: 's', + TIMEZONE: 'Asia/Shanghai', + NOTIFICATION_HOURS: ['*'], + ENABLED_NOTIFIERS: ['telegram'], + TG_BOT_TOKEN: 'B', + TG_CHAT_ID: 'C' + }); + await subRepo.save(env, { + id: 's-wc', + name: 'WC', + isActive: true, + autoRenew: false, + expiryDate: '2026-05-25T03:00:00.000Z' + }); + await remindersRepo.replaceForSubscription(env, 's-wc', [ + remindersRepo.normalizeRule({ type: 'before_expiry', value: 1, unit: 'days' }) + ]); + + mockTelegramOk(); + const log = await checkExpiringSubscriptions(env); + expect(log.inWindow).toBe(true); + expect(log.configuredHours).toEqual(['*']); + expect(log.sentCount).toBe(1); + }); }); describe('scheduler v3 - 自动续订', () => { diff --git a/wrangler.dev.toml b/wrangler.dev.toml new file mode 100644 index 0000000..af2b450 --- /dev/null +++ b/wrangler.dev.toml @@ -0,0 +1,27 @@ +# 本地开发专用配置(v3) +# +# 用法:npx wrangler dev --config wrangler.dev.toml +# +# 与 wrangler.toml 的差异: +# - 内联了一个 KV 命名空间假 ID,让 miniflare 模拟 KV 时不再报"未绑定" +# - 不动主 wrangler.toml,避免与 npm run setup 自动写入的 KV 块冲突 +name = "subscription-manager-dev" +main = "src/index.js" +compatibility_date = "2024-09-23" +compatibility_flags = ["nodejs_compat"] + +# 本地用的占位 KV,miniflare 会自动用 .wrangler/state 下的本地 KV 文件 +[[kv_namespaces]] +binding = "SUBSCRIPTIONS_KV" +id = "local-dev-kv-placeholder" +preview_id = "local-dev-kv-preview" + +[assets] +directory = "./public" +binding = "ASSETS" + +[triggers] +crons = ["0 * * * *"] + +[vars] +ENVIRONMENT = "development"