amqplib-init 1.1.6 → 1.1.7

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.
Files changed (3) hide show
  1. package/demo.js +5 -0
  2. package/index.js +93 -102
  3. package/package.json +2 -1
package/demo.js ADDED
@@ -0,0 +1,5 @@
1
+ const init = require('./index')
2
+ init.init({
3
+ channelName: 'amqplib-test-query',
4
+ amqpLink: ``
5
+ })
package/index.js CHANGED
@@ -1,119 +1,110 @@
1
1
  const amqp = require('amqplib');
2
2
  const shelljs = require('shelljs');
3
- const chalk = require('chalk-style');
3
+ const log = require('chalk-style')
4
+ const happy = require('happy-help');
4
5
 
5
- const sleep = (time) => {
6
- return new Promise(resolve => {
7
- setTimeout(_ => resolve(), time * 1000)
8
- })
9
- };
10
6
  module.exports = {
11
- /**
12
- * 消息队列设置
13
- * @returns {Promise<unknown>}
14
- * @param option
15
- */
16
- init (option){
7
+ // 初始化函数
8
+ init(option) {
17
9
  const {
18
- channelName = 'node-test-channel',
19
- prefetch = 1,
20
- pmId = 0,
21
- callback = ()=> {},
22
- finish = ()=> {},
23
- amqpLink = ``,
24
- heartbeat = 5,
25
- timeout = 120000,
26
- delay = 0,
27
- autoReload = 0,
28
- queryHook = () => {},
29
- init = () => {}
10
+ channelName = 'node-test-channel', // 频道名称,默认为'node-test-channel'
11
+ prefetch = 1, // 预取计数,默认为1
12
+ pmId = 0, // PM2进程ID,默认为0
13
+ callback = () => {}, // 消息处理回调,默认为空函数
14
+ finish = () => {}, // 初始化完成回调,默认为空函数
15
+ amqpLink = '', // RabbitMQ连接地址
16
+ heartbeat = 5, // 心跳间隔,单位为秒,默认为2秒
17
+ timeout = 2000, // 连接超时时间,单位为毫秒,默认为10000毫秒
18
+ delay = 0, // 消息处理完成后延迟ack的时间,单位为毫秒,默认为0毫秒
19
+ autoReload = 0, // 自动重载间隔时间,单位为毫秒,默认为0毫秒(不自动重载)
20
+ queryHook = () => {}, // 查询钩子,默认为空函数(用于判断是否有其他消息来源)
21
+ initHook = () => {} // 初始化钩子,默认为空函数(在连接成功后执行)
30
22
  } = option;
31
- const durable = true;
32
- chalk.log(`🚀 队列已执行...`);
33
- let connect = null;
34
- const amqpInit = async (reload = false) => {
35
- await sleep(1); // 等待一秒钟
36
- connect = await amqp.connect(amqpLink, {
37
- heartbeat, // 心跳检测5秒
38
- timeout, // 设置连接超时时间为120
39
- });
40
- if (pmId > 0 && reload){
41
- chalk.log(`‼️ 服务即将重启`);
42
- shelljs.exec(`pm2 reload ${pmId}`);
43
- }
44
- }
45
- return new Promise(async (resolve) => {
46
- await amqpInit();
47
- chalk.log(`✳️->RabbitMQ链接成功`);
48
- const channel = await connect.createChannel();
49
- chalk.log(`✳️->数据队列名称`, channelName);
50
- chalk.log(`✳️->是否持久化`, durable);
51
- const { queue } = await channel.assertQueue(channelName, { durable });
52
- // 从这里绑定交换机;
53
- await init && init({ channel, connect });
54
- // 一次性读取一条;
23
+ const durable = true; // 队列是否持久化,默认为true
24
+ let connection = null; // RabbitMQ连接
25
+ let channel = null; // RabbitMQ频道
26
+
27
+ // 重连函数
28
+ const reconnect = async () => {
29
+ log.error('连接丢失,正在尝试重连...');
30
+ await happy.sleep(2); // 重连前等待2
31
+ connection = await amqp.connect(amqpLink, { heartbeat, timeout });
32
+ channel = await connection.createChannel();
33
+ await channel.assertQueue(channelName, { durable });
55
34
  await channel.prefetch(prefetch);
56
- chalk.log(`✳️->一次取多少条`, prefetch);
57
- chalk.log(`✳️->消息队列: ${channelName} 正在运行中...`);
58
- await channel.consume(queue, async (msg) => {
35
+ await initHook({ channel, connection }); // 执行初始化钩子
36
+ log.log(`已重新连接到RabbitMQ,频道: ${channelName}`);
37
+ await consumeMessages(); // 开始消费消息
38
+ };
39
+
40
+ // 消费消息函数
41
+ const consumeMessages = async () => {
42
+ log.log(`开始消费: ${channelName}`);
43
+ await channel.consume(channelName, async (msg) => {
59
44
  if (msg !== null) {
60
45
  try {
61
- await channel.assertQueue(channelName, { durable });
62
- const content = JSON.parse(msg?.content?.toString());
63
- chalk.log(`✳️->队列收到新消息: ${channelName}`);
64
- const startTime = new Date().getTime();
65
- callback(content).then(()=> {
66
- try {
67
- setTimeout(_=> {
68
- const endTime = (new Date().getTime() - startTime);
69
- chalk.log(`✳️->消息处理完成, 需要延迟: ${delay}ms, 共耗时: ${endTime}ms`);
70
- channel.ack(msg);
71
- }, delay)
72
- } catch (e) {
73
- chalk.warning(`队列消费遇到异常`, e);
74
- channel.reject(msg,true);
75
- }
76
- }).catch(e => {
77
- chalk.warning(`消息处理遇到异常`, e);
78
- channel.reject(msg, true);
79
- });
46
+ const content = JSON.parse(msg.content.toString());
47
+ log.log(`收到消息: ${JSON.stringify(content)}`);
48
+ const startTime = Date.now();
49
+ await callback(content); // 执行消息处理回调
50
+ const endTime = Date.now() - startTime;
51
+ log.log(`消息处理完成,延迟: ${delay}ms,总时间: ${endTime}ms`);
52
+ setTimeout(() => channel.ack(msg), delay); // 延迟ack
80
53
  } catch (e) {
81
- chalk.error(`队列遇到异常`, e);
54
+ log.error('处理消息时出错:', e);
55
+ channel.reject(msg, true); // 拒绝消息并重新排队
82
56
  }
83
57
  } else {
84
- chalk.log(`消息异常`, msg);
58
+ log.error('收到无效消息:', msg);
85
59
  }
86
60
  }, { noAck: false });
87
- // 队列遇到错误
88
- connect.on('error', (err) => {
89
- chalk.log('Connection error', err.message);
90
- amqpInit(true);
91
- });
92
- // 队列被关闭
93
- connect.on('close', function() {
94
- chalk.log('Connection to RabbitMQ is closed');
95
- amqpInit(true);
96
- });
97
- chalk.log(`✳️-队列已启动: finish~`);
98
- if (autoReload > 0) {
99
- console.log(`❤️ 将在 ${autoReload}ms 秒后自动重启!!!`)
100
- setInterval(async _=> {
101
- try {
102
- const result = await channel.checkQueue(channelName);
103
- const messageCount = result.messageCount;
104
- console.log(`MQ队列中有 ${messageCount} 条消息`);
105
- const length = queryHook ? !!queryHook() : 0;
106
- console.log(`REDIS队列中有 ${messageCount} 条消息`);
107
- if (messageCount <= 0 && length === 0) {
108
- console.log(`即将重启此服务~`);
109
- shelljs.exec(`pm2 reload ${pmId}`);
61
+ };
62
+
63
+ // 启动函数
64
+ const start = async () => {
65
+ try {
66
+ connection = await amqp.connect(amqpLink, { heartbeat, timeout });
67
+ channel = await connection.createChannel();
68
+ await channel.assertQueue(channelName, { durable });
69
+ await channel.prefetch(prefetch);
70
+ await initHook({ channel, connection }); // 执行初始化钩子
71
+ log.log(`已连接到RabbitMQ,频道: ${channelName}`);
72
+ await consumeMessages(); // 开始消费消息
73
+ // 连接错误处理
74
+ connection.on('error', (err) => {
75
+ log.error('连接错误:', err.message);
76
+ reconnect(); // 尝试重连
77
+ });
78
+
79
+ // 连接关闭处理
80
+ connection.on('close', () => {
81
+ log.error('与RabbitMQ的连接已关闭');
82
+ reconnect(); // 尝试重连
83
+ });
84
+
85
+ // 自动重载逻辑
86
+ if (autoReload > 0) {
87
+ setInterval(async () => {
88
+ try {
89
+ const { messageCount } = await channel.checkQueue(channelName);
90
+ const redisLength = queryHook() ? 1 : 0; // 假设queryHook返回真值表示有消息
91
+ log.log(`MQ队列中有 ${messageCount} 条消息,REDIS中有 ${redisLength} 条消息`);
92
+ if (messageCount === 0 && redisLength === 0) {
93
+ log.log('队列中没有消息,正在重载服务...');
94
+ shelljs.exec(`pm2 reload ${pmId}`); // 使用PM2重载服务
95
+ }
96
+ } catch (e) {
97
+ log.error('检查队列长度时出错:', e);
110
98
  }
111
- } catch (e) {
112
- console.log(`重启失败~`);
113
- }
114
- }, autoReload)
99
+ }, autoReload);
100
+ }
101
+
102
+ finish(); // 执行初始化完成回调
103
+ } catch (e) {
104
+ log.error('初始化RabbitMQ连接时出错:', e);
115
105
  }
116
- finish && finish();
117
- })
106
+ };
107
+ // 返回启动函数并立即执行
108
+ return start();
118
109
  }
119
- }
110
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amqplib-init",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "description": "消息队列初始化",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -11,6 +11,7 @@
11
11
  "dependencies": {
12
12
  "amqplib": "^0.10.4",
13
13
  "chalk-style": "^1.0.0",
14
+ "happy-help": "^1.0.1",
14
15
  "js-base64": "^3.7.7",
15
16
  "shelljs": "^0.8.5"
16
17
  }