nayota-energy-ms-sdk 0.0.1
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.
- package/README.md +10 -0
- package/config.js +11 -0
- package/distribute.js +9 -0
- package/index.js +41 -0
- package/package.json +11 -0
- package/redis/base.js +127 -0
- package/redis/energyRecord.consumer.js +10 -0
- package/seneca/checks.seneca.js +16 -0
- package/seneca.error.js +6 -0
package/README.md
ADDED
package/config.js
ADDED
package/distribute.js
ADDED
package/index.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const config = require('./config')
|
|
2
|
+
const checks = require('./seneca/checks.seneca')
|
|
3
|
+
const EnergyRecords = require('./redis/energyRecord.consumer')
|
|
4
|
+
const distribute = require('./distribute')
|
|
5
|
+
const redisObj = {}
|
|
6
|
+
|
|
7
|
+
const sdk = {
|
|
8
|
+
init: function(seneca, redis, role, version) {
|
|
9
|
+
config.role = role
|
|
10
|
+
config.version = version
|
|
11
|
+
if (seneca)config.setSeneca(seneca)
|
|
12
|
+
if (redis) {
|
|
13
|
+
config.setRedis(redis)
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
seneca: { // 开放seneca接口
|
|
17
|
+
checks
|
|
18
|
+
},
|
|
19
|
+
on: (topic, cb) => {
|
|
20
|
+
switch (topic) {
|
|
21
|
+
case 'energyRecords':
|
|
22
|
+
if (!redisObj.energyRecords) {
|
|
23
|
+
redisObj.energyRecords = new EnergyRecords()
|
|
24
|
+
redisObj.energyRecords.start()
|
|
25
|
+
}
|
|
26
|
+
break
|
|
27
|
+
default:
|
|
28
|
+
break
|
|
29
|
+
}
|
|
30
|
+
distribute.on(topic, cb)
|
|
31
|
+
},
|
|
32
|
+
close: () => {
|
|
33
|
+
for (const key in redisObj) {
|
|
34
|
+
if (redisObj[key].stop) {
|
|
35
|
+
redisObj[key].stop()
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = sdk
|
package/package.json
ADDED
package/redis/base.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author lifeng
|
|
3
|
+
* @date 23-11-17
|
|
4
|
+
* @Description: 消息队列流接口
|
|
5
|
+
*/
|
|
6
|
+
const config = require('../config')
|
|
7
|
+
const em = require('../distribute')
|
|
8
|
+
|
|
9
|
+
class Base {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.stop = true
|
|
12
|
+
this.key = 'server:base'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async start() {
|
|
16
|
+
if (!config.redis) return
|
|
17
|
+
const client = config.redis
|
|
18
|
+
try {
|
|
19
|
+
await client.xGroupCreate(this.key, config.role, '0', { // 在一个流数据上建立一个分组 第一个参数是流的key,第二个参数是分组名 第三个参数,是从流的哪个ID开始取值,0是从开头,$是从结尾
|
|
20
|
+
MKSTREAM: true // 添加这个参数 则会判定如果流不存在 自动创建对应流 默认流不存在创建分组会报错
|
|
21
|
+
})
|
|
22
|
+
console.log(this.key, 'Created consumer group.')
|
|
23
|
+
} catch (e) {
|
|
24
|
+
console.log(this.key, 'Consumer group already exists, skipped creation.')
|
|
25
|
+
}
|
|
26
|
+
// console.log(`Starting consumer ${config.version}.`)
|
|
27
|
+
await this.xPending()
|
|
28
|
+
this.stop = false
|
|
29
|
+
while (!this.stop) {
|
|
30
|
+
try {
|
|
31
|
+
const response = await client.xReadGroup(
|
|
32
|
+
client.commandOptions({
|
|
33
|
+
isolated: true
|
|
34
|
+
}),
|
|
35
|
+
config.role, // 组名
|
|
36
|
+
config.version, // 消费者名 每一个消费者都应该有自己唯一的消费者名
|
|
37
|
+
[
|
|
38
|
+
{
|
|
39
|
+
key: this.key,
|
|
40
|
+
id: '>' // Id有两种类型,一种为>符号,代表只读取新消息(从未读取过的),任何其他Id,会读取到已经被读取过但未确认处理的
|
|
41
|
+
}
|
|
42
|
+
], {
|
|
43
|
+
// Read 1 entry at a time, block for 5 seconds if there are none.
|
|
44
|
+
COUNT: 1, // 一次最多读取几条消息
|
|
45
|
+
BLOCK: 5000 // 超时时间,超时返回空回复
|
|
46
|
+
// NOACK: true // 读取到就确认 BLOCK NOACK 这两个参数只对id为>有效
|
|
47
|
+
}
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
if (response) {
|
|
51
|
+
if (response[0].messages[0]) {
|
|
52
|
+
const entryId = response[0].messages[0].id
|
|
53
|
+
await this.handle(response[0].messages[0].message) // 处理消息
|
|
54
|
+
await client.xAck(this.key, config.role, entryId) // 提交 消息消费成功 消息消费后必须提交,不然消息将处于已读取待处理状态 可通过XPENDING命令查看是否有待处理命令,然后提取,再次处理 也可以在读取消息的时候标记NOACK 表示此命令读取到就已处理,这样可能会造成偶尔的数据丢失
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
} catch (err) {
|
|
58
|
+
console.error(err)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 检查是否有已读取过未处理消息
|
|
64
|
+
async xPending() {
|
|
65
|
+
if (!config.client) return
|
|
66
|
+
const client = config.redis
|
|
67
|
+
const response = await client.xPending( // 查询 是否有已读未确认消息。一般用于消息有问题或者当接受端的服务突然崩溃时,重新获取消息再处理
|
|
68
|
+
client.commandOptions({
|
|
69
|
+
isolated: true
|
|
70
|
+
}),
|
|
71
|
+
this.key, // 流key
|
|
72
|
+
config.role, // 分组名
|
|
73
|
+
config.version // 消费者名
|
|
74
|
+
)
|
|
75
|
+
if (response && response.pending > 0) {
|
|
76
|
+
this.getPending(response.firstId, response.lastId)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 获取1条已读未确认消息
|
|
81
|
+
async getPending(firstId, lastId) {
|
|
82
|
+
if (!config.redis) return
|
|
83
|
+
console.log(firstId, lastId)
|
|
84
|
+
const client = config.redis
|
|
85
|
+
let currentId = null
|
|
86
|
+
while (currentId !== lastId) {
|
|
87
|
+
try {
|
|
88
|
+
const response = await client.xReadGroup(
|
|
89
|
+
client.commandOptions({
|
|
90
|
+
isolated: true
|
|
91
|
+
}),
|
|
92
|
+
config.role,
|
|
93
|
+
config.version,
|
|
94
|
+
[
|
|
95
|
+
{
|
|
96
|
+
key: this.key,
|
|
97
|
+
id: firstId
|
|
98
|
+
}
|
|
99
|
+
], {
|
|
100
|
+
COUNT: 1
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
if (response && response[0].messages[0]) {
|
|
104
|
+
currentId = response[0].messages[0].id
|
|
105
|
+
await this.handle(response[0].messages[0].message) // 处理消息
|
|
106
|
+
await client.xAck(this.key, config.role, currentId)
|
|
107
|
+
} else {
|
|
108
|
+
break
|
|
109
|
+
}
|
|
110
|
+
} catch (err) {
|
|
111
|
+
console.error(err)
|
|
112
|
+
await client.xAck(this.key, config.role, firstId)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// 处理消息
|
|
118
|
+
async handle(message) {
|
|
119
|
+
em.emit(this.key.split(':').slice(-1)[0], message)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
stop() {
|
|
123
|
+
this.stop = true
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
module.exports = Base
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const seneca = require('../config')
|
|
2
|
+
const { SUCCESS } = require('../seneca.error')
|
|
3
|
+
const Promise = require('bluebird')
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
list
|
|
7
|
+
}
|
|
8
|
+
async function list(option) {
|
|
9
|
+
const act = Promise.promisify(seneca.seneca.act, { context: seneca.seneca })
|
|
10
|
+
const result = await act({ role: 'nayota-config-server-prod', cmd: 'check-all-user-data', data: option })
|
|
11
|
+
if (result.code !== SUCCESS) {
|
|
12
|
+
throw new Error(result.message)
|
|
13
|
+
}
|
|
14
|
+
return result.data
|
|
15
|
+
}
|
|
16
|
+
|