Files
memind/notification-dispatcher.mjs
T
john d820247aa1
Memind CI / Test, build, and release guards (push) Successful in 3m32s
fix(schedule): retry reminders when WeChat delivery is deferred
Treat deferred/skipped customer-service sends as failures so reminder worker
does not mark reminders sent, and add a 103 read-only health check script.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-16 21:30:53 +08:00

66 lines
2.1 KiB
JavaScript

export const WECHAT_SCHEDULE_NOTIFICATION_NOT_SENT =
'WECHAT_SCHEDULE_NOTIFICATION_NOT_SENT';
export function resolveWechatDispatchSent(result) {
if (result && typeof result === 'object') {
return result.sent !== false && !result.deferred && !result.skipped;
}
return result !== false;
}
export async function deliverWechatScheduleNotification(
sendScheduleNotification,
payload,
) {
const result = await sendScheduleNotification(payload);
if (!resolveWechatDispatchSent(result)) {
const err = new Error('微信提醒发送未完成(deferred、skipped 或未绑定)');
err.code = WECHAT_SCHEDULE_NOTIFICATION_NOT_SENT;
throw err;
}
}
export function createNotificationDispatcher({ sendWechatTextToUser, logger = console } = {}) {
const sendWechat = async (userId, text, options = {}) => {
if (typeof sendWechatTextToUser !== 'function') return false;
const result = await sendWechatTextToUser(userId, text, options);
return resolveWechatDispatchSent(result);
};
return {
async sendRechargeSuccess({ userId, title, body, dedupeKey = null }) {
const sent = await sendWechat(userId, `${title}\n${body}`.trim());
logger.info?.('Notification dispatch:', {
type: 'recharge_success',
userId,
dedupeKey,
sent,
});
return sent;
},
async sendScheduleNotification({ userId, text, verifiedHtmlUrls = [] }) {
const sent = await sendWechat(userId, text, { verifiedHtmlUrls });
logger.info?.('Notification dispatch:', {
type: 'schedule_notification',
userId,
dedupeKey: null,
sent,
verifiedHtmlCount: verifiedHtmlUrls.length,
});
return sent;
},
async sendHealthEventNotification({ userId, title, body, eventId = null, severity = 'alert' }) {
const text = `${title}\n${body}`.trim();
const sent = await sendWechat(userId, text);
logger.info?.('Notification dispatch:', {
type: 'health_event_notification',
userId,
dedupeKey: eventId,
severity,
sent,
});
return sent;
},
};
}