定时任务改为按用户分组、按优先级发送,额度耗尽即停
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert')
|
||||
const { useTempDb } = require('./helper')
|
||||
|
||||
useTempDb()
|
||||
const db = require('../src/db')
|
||||
const wx = require('../src/wx')
|
||||
const quota = require('../src/quota')
|
||||
const reminder = require('../src/reminder')
|
||||
|
||||
// 用「今天」为基准造数据,保证 daysUntil 落在期望值上
|
||||
const TODAY = new Date()
|
||||
const inDays = (n) => new Date(TODAY.getTime() + n * 86400000)
|
||||
|
||||
function makeAnniv(id, openid, personName, importance, offsetDays, remindDays) {
|
||||
const d = inDays(offsetDays)
|
||||
return {
|
||||
id, openid, personId: 'p', personName, type: 'birthday',
|
||||
isLunar: 0, solarYear: d.getFullYear(), solarMonth: d.getMonth() + 1, solarDay: d.getDate(),
|
||||
importance, remindEnabled: 1, remindDays
|
||||
}
|
||||
}
|
||||
|
||||
function resetLogs() {
|
||||
db.prepare('DELETE FROM remind_logs').run()
|
||||
}
|
||||
|
||||
test('额度够时全部发出', async () => {
|
||||
resetLogs()
|
||||
quota.grant('uA', 5)
|
||||
const sent = []
|
||||
const restore = wx.sendSubscribeMessage
|
||||
wx.sendSubscribeMessage = async (p) => { sent.push(p.data.name1.value); return { errcode: 0 } }
|
||||
|
||||
const items = [
|
||||
makeAnniv('A1', 'uA', '甲', 'low', 0, 3),
|
||||
makeAnniv('A2', 'uA', '乙', 'high', 0, 3)
|
||||
]
|
||||
const r = await reminder.runForUser('uA', items, TODAY)
|
||||
wx.sendSubscribeMessage = restore
|
||||
|
||||
assert.strictEqual(r.ok, 2)
|
||||
assert.strictEqual(r.skipped, 0)
|
||||
assert.strictEqual(quota.getBalance('uA'), 3)
|
||||
})
|
||||
|
||||
test('额度不足时当天优先、同级按重要程度', async () => {
|
||||
resetLogs()
|
||||
quota.grant('uB', 1)
|
||||
const sent = []
|
||||
const restore = wx.sendSubscribeMessage
|
||||
wx.sendSubscribeMessage = async (p) => { sent.push(p.data.name1.value); return { errcode: 0 } }
|
||||
|
||||
const items = [
|
||||
makeAnniv('B1', 'uB', '提前的', 'high', 3, 3), // 提前事件(daysUntil=3=remindDays)
|
||||
makeAnniv('B2', 'uB', '当天低', 'low', 0, 3), // 当天事件
|
||||
makeAnniv('B3', 'uB', '当天高', 'high', 0, 3) // 当天事件,重要程度更高
|
||||
]
|
||||
const r = await reminder.runForUser('uB', items, TODAY)
|
||||
wx.sendSubscribeMessage = restore
|
||||
|
||||
assert.strictEqual(r.ok, 1)
|
||||
assert.strictEqual(r.skipped, 2)
|
||||
assert.deepStrictEqual(sent, ['当天高'], '应当只发出当天且最重要的那条')
|
||||
})
|
||||
|
||||
test('余额为 0 时不发任何请求', async () => {
|
||||
resetLogs()
|
||||
let called = 0
|
||||
const restore = wx.sendSubscribeMessage
|
||||
wx.sendSubscribeMessage = async () => { called++; return { errcode: 0 } }
|
||||
|
||||
const items = [makeAnniv('C1', 'uC', '丙', 'high', 0, 3)]
|
||||
const r = await reminder.runForUser('uC', items, TODAY)
|
||||
wx.sendSubscribeMessage = restore
|
||||
|
||||
assert.strictEqual(called, 0, '没额度就不该打请求')
|
||||
assert.strictEqual(r.skipped, 1)
|
||||
})
|
||||
|
||||
test('遇到 43101 立即归零并中止本用户剩余发送', async () => {
|
||||
resetLogs()
|
||||
quota.grant('uD', 9)
|
||||
let called = 0
|
||||
const restore = wx.sendSubscribeMessage
|
||||
wx.sendSubscribeMessage = async () => {
|
||||
called++
|
||||
const e = new Error('发送订阅消息失败')
|
||||
e.errcode = 43101
|
||||
throw e
|
||||
}
|
||||
|
||||
const items = [
|
||||
makeAnniv('D1', 'uD', '甲', 'high', 0, 3),
|
||||
makeAnniv('D2', 'uD', '乙', 'high', 0, 3),
|
||||
makeAnniv('D3', 'uD', '丙', 'high', 0, 3)
|
||||
]
|
||||
const r = await reminder.runForUser('uD', items, TODAY)
|
||||
wx.sendSubscribeMessage = restore
|
||||
|
||||
assert.strictEqual(called, 1, '失败一次就该停,不该继续打请求')
|
||||
assert.strictEqual(quota.getBalance('uD'), 0, '余额应被归零校正')
|
||||
assert.strictEqual(r.skipped, 3, '含失败那条在内全部计为 skipped')
|
||||
})
|
||||
|
||||
test('非额度类错误只记 failed,不动余额', async () => {
|
||||
resetLogs()
|
||||
quota.grant('uE', 4)
|
||||
const restore = wx.sendSubscribeMessage
|
||||
wx.sendSubscribeMessage = async () => {
|
||||
const e = new Error('网络炸了')
|
||||
e.errcode = 40003
|
||||
throw e
|
||||
}
|
||||
|
||||
const items = [makeAnniv('E1', 'uE', '甲', 'high', 0, 3)]
|
||||
const r = await reminder.runForUser('uE', items, TODAY)
|
||||
wx.sendSubscribeMessage = restore
|
||||
|
||||
assert.strictEqual(r.fail, 1)
|
||||
assert.strictEqual(quota.getBalance('uE'), 4, '配置/网络错误不该动余额')
|
||||
})
|
||||
|
||||
test('skipped 会写入 remind_logs 便于排查', async () => {
|
||||
resetLogs()
|
||||
const items = [makeAnniv('F1', 'uF', '甲', 'high', 0, 3)]
|
||||
await reminder.runForUser('uF', items, TODAY)
|
||||
const row = db.prepare("SELECT * FROM remind_logs WHERE status = 'skipped'").get()
|
||||
assert.ok(row, '应写入 skipped 日志')
|
||||
assert.strictEqual(row.error, 'quota_exhausted')
|
||||
})
|
||||
Reference in New Issue
Block a user