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 ADDED
@@ -0,0 +1,10 @@
1
+ # Nayota服务端微服务SDK
2
+ ```
3
+ yarn add nayota-energy-ms-sdk
4
+ ```
5
+ ## 使用方法
6
+ ```javascript
7
+ import NayotaEnergyMsSdk from 'nayota-energy-ms-sdk'
8
+
9
+ NayotaEnergyMsSdk.init(seneca, redis, role, version)
10
+ ```
package/config.js ADDED
@@ -0,0 +1,11 @@
1
+
2
+ module.exports = {
3
+ setSeneca: function(seneca) {
4
+ this.seneca = seneca
5
+ },
6
+ setRedis: function(redis) {
7
+ this.redis = redis
8
+ },
9
+ role: '',
10
+ version: ''
11
+ }
package/distribute.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @author lifeng
3
+ * @date 20-10-23
4
+ * @Description: 应用与服务全局的监听对象
5
+ */
6
+ const EventEmitter = require('events').EventEmitter
7
+ const listenBroker = new EventEmitter()
8
+ listenBroker.setMaxListeners(50) // 增大单个监听的监听上限
9
+ module.exports = new EventEmitter()
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
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "nayota-energy-ms-sdk",
3
+ "version": "0.0.1",
4
+ "description": "nayota-energy-server后台微服务",
5
+ "main": "index.js",
6
+ "author": "zhutianxiang",
7
+ "license": "MIT",
8
+ "dependencies": {
9
+ "bluebird": "^3.7.2"
10
+ }
11
+ }
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,10 @@
1
+ const Base = require('./base')
2
+
3
+ class EnergyRecordConsumer extends Base {
4
+ constructor() {
5
+ super()
6
+ this.key = 'nayota-opoec-server:energyRecords'
7
+ }
8
+ }
9
+
10
+ module.exports = EnergyRecordConsumer
@@ -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
+
@@ -0,0 +1,6 @@
1
+ // ERROR CODE
2
+
3
+ module.exports = {
4
+ SUCCESS: 0,
5
+ ERROR: 1
6
+ }