@sadikkhan02/notifykit (核心)
代码优先,用于Node.js和TypeScript的无状态通知编排库。
@sadikkhan02/notifykit 提供了一个统一的多通道通知引擎,由BullMQ和Redis提供支持。它允许应用程序快速排队通知,在内存中可靠地预呈现模板,并通过持久的重试逻辑、自动错误分类和死信队列(DLQ)保护跨Email、SMS和Push通知通道传递消息。
功能
- 统一多通道API:单
notifier.notify()方法同时针对邮件、短信和推送。 - 使用BullMQ进行持久队列: Redis流支持的持久后台作业处理。
- 快速故障内存预渲染:模板渲染 之前 队列(ADR-004),防止语法错误或缺少变量进入Redis。
- 指数后退重试:自动重试瞬态提供商/网络故障(最多5次尝试与抖动)。
- 死信队列(DLQ):自动隔离不可重试的故障(无效的电话号码、格式错误的电子邮件、身份验证拒绝)。
- 关联与分布式跟踪:每个事件生成一个按时间顺序排列的uidv7跟踪ID,它在队列、工作者、日志和适配器调用之间传播。
- 自动秘密和PII修订:敏感领域(
auth.pass,token,phone,email,authorization)在结构化日志中剥离。 - 可插拔适配器架构:与Nodemailer、Twilio、MSG91和Firebase Cloud Messaging (FCM)的官方适配器兼容。
安装
npm install @sadikkhan02/notifykit
安装所需的适配器:
# Email (Universal SMTP, SendGrid, Gmail, Mailtrap)
npm install @sadikkhan02/adapter-nodemailer nodemailer
# SMS (Twilio)
npm install @sadikkhan02/adapter-twilio twilio
# SMS (MSG91 - India DLT optimized, native fetch, zero vendor SDK)
npm install @sadikkhan02/adapter-msg91
# Push (Firebase Cloud Messaging)
npm install @sadikkhan02/adapter-fcm firebase-admin
快速入门
import { createNotifier } from '@sadikkhan02/notifykit';
import { NodemailerEmailProvider } from '@sadikkhan02/adapter-nodemailer';
// 1. Initialize the Notifier
const notifier = createNotifier({
redis: process.env.REDIS_URL || 'redis://localhost:6379',
providers: {
email: {
type: 'nodemailer',
adapter: new NodemailerEmailProvider({
host: process.env.SMTP_HOST || 'smtp.mailtrap.io',
port: Number(process.env.SMTP_PORT) || 587,
auth: {
user: process.env.SMTP_USER || 'mock_user',
pass: process.env.SMTP_PASSWORD || 'mock_pass',
},
}),
from: '[email protected]',
},
},
});
// 2. Register a template
notifier.registerTemplate(
'welcome-email',
'<h1>Welcome, {{name}}!</h1><p>Your account is ready.</p>',
);
// 3. Enqueue notification (guarantees durable Redis acceptance)
const { jobId } = await notifier.notify({
to: { email: '[email protected]' },
channels: ['email'],
template: 'welcome-email',
data: { name: 'Alice' },
});
console.log(`Notification enqueued with ID: ${jobId}`);
// 4. Start processing background queues
notifier.startWorker({ channels: ['email'], concurrency: 5 });
// 5. Gracefully shutdown on termination signals
process.on('SIGINT', async () => {
await notifier.stopWorker();
process.exit(0);
});
核心API参考
createNotifier(options?: CreateNotifierOptions): Notifier
工厂功能,用于创建已配置的 Notifier 协调器实例。
选项(CreateNotifierOptions)
| 选项 | 类型 | 描述 |
|---|---|---|
redis | string | Redis连接URL(例如: redis://localhost:6379). 默认为 process.env.REDIS_URL. |
providers | NotifierConfig['providers'] | 通道提供者映射(email, sms, push)。 |
templates | Record<string, string> | 初始模板字典 [id]: source. |
logLevel | LogLevel | Pino日志级别(fatal, error, warn, info, debug, trace, silent)。 |
logger | Logger | 自定义Pino记录器实例。 |
notifier.notify(event: NotificationEvent): Promise<NotifyResult>
验证事件,在内存中预呈现模板,解析通道适配器,并自动将作业排队给Redis。
重要的区别:排队与交付
await notifier.notify(...)一旦通知被安全地保存在Redis队列中,就会解析。它返回{ jobId: string }. 实际传输到SMTP、Twilio、MSG91或FCM是在后台worker异步进行的。
事件架构(NotificationEvent)
export interface NotificationEvent {
to: {
email?: string; // RFC 5322 formatted email
phone?: string; // E.164 formatted phone number (+15555550100)
pushToken?: string; // FCM device registration token
};
channels: Array<'email' | 'sms' | 'push'>;
template: string; // Registered template ID
data: Record<string, unknown>; // Template variables
}
notifier.registerTemplate(id: string, source: string): void
编译并在内存中缓存Handlebars模板。支持内置帮助器:
{{uppercase text}}:将文本转换为大写。{{formatDate timestamp}}:安全地格式化日期。
notifier.startWorker(options?: StartWorkerOptions): void
启动BullMQ队列工作者,以使用和分派已排队的通知。
notifier.startWorker({
channels: ['email', 'sms'], // Channels to process (defaults to all configured)
concurrency: { email: 10, sms: 5 }, // Global number or per-channel overrides
});
notifier.stopWorker(): Promise<void>
清除正在运行的作业并干净地暂停队列工作。在应用程序进程退出之前调用此函数。
全局连接拆解
对于独立脚本和自动化测试,关闭队列实例和共享Redis连接池:
import { resetDefaultRegistry, closeRedisConnection } from 'notifykit';
await notifier.stopWorker();
await resetDefaultRegistry();
await closeRedisConnection();
重试策略&死信队列(DLQ)
NotifyKit遵循严格的交付弹性策略:
- 瞬态误差(
retryable: true):- 连接超时、HTTP 429速率限制和5xx网关错误自动重试 5倍.
- 退避策略:随机抖动的指数退避(
1s,2s,4s,8s,16s)。
- 终端错误(
retryable: false):- 无效的电话号码(例如Twilio)
21211), DLT注册拒绝(MSG91),未注册的推送令牌(FCM)或身份验证失败立即绕过重试并直接路由到bull:notifykit:dlq:*. - DLQ作业将无限期保留,以便事后分析。
- 无效的电话号码(例如Twilio)
许可证
麻省理工学院