oak-backend-base 3.1.2 → 3.2.0
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/lib/AppLoader.d.ts +32 -31
- package/lib/AppLoader.js +344 -343
- package/lib/DataSubscriber.d.ts +18 -18
- package/lib/DataSubscriber.js +158 -148
- package/lib/DbStore.d.ts +18 -18
- package/lib/DbStore.js +116 -116
- package/lib/cluster/DataSubscriber.d.ts +18 -0
- package/lib/cluster/DataSubscriber.js +158 -0
- package/lib/cluster/env.d.ts +5 -0
- package/lib/cluster/env.js +41 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +7 -5
- package/lib/polyfill.d.ts +3 -3
- package/package.json +41 -41
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const lodash_1 = require("oak-domain/lib/utils/lodash");
|
|
4
|
+
const oak_domain_1 = require("oak-domain");
|
|
5
|
+
class DataSubscriber {
|
|
6
|
+
ns;
|
|
7
|
+
contextBuilder;
|
|
8
|
+
filterMap;
|
|
9
|
+
idEntityMap;
|
|
10
|
+
constructor(ns, contextBuilder) {
|
|
11
|
+
this.ns = ns;
|
|
12
|
+
this.contextBuilder = contextBuilder;
|
|
13
|
+
this.startup();
|
|
14
|
+
this.filterMap = {};
|
|
15
|
+
this.idEntityMap = {};
|
|
16
|
+
}
|
|
17
|
+
formCreateRoomRoutine(def) {
|
|
18
|
+
const { id, entity, filter } = def;
|
|
19
|
+
return (room) => {
|
|
20
|
+
if (room === id) {
|
|
21
|
+
console.log('instance:', process.env.NODE_APP_INSTANCE, 'add filter', room);
|
|
22
|
+
// 本房间不存在,说明这个filter是新出现的
|
|
23
|
+
if (this.filterMap[entity]) {
|
|
24
|
+
// id的唯一性由前台保证,重复则无视
|
|
25
|
+
Object.assign(this.filterMap[entity], {
|
|
26
|
+
[id]: filter,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
Object.assign(this.filterMap, {
|
|
31
|
+
[entity]: {
|
|
32
|
+
[id]: filter,
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
this.idEntityMap[id] = entity;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 来自外部的socket连接,监听数据变化
|
|
42
|
+
*/
|
|
43
|
+
startup() {
|
|
44
|
+
this.ns.on('connection', async (socket) => {
|
|
45
|
+
try {
|
|
46
|
+
const { 'oak-cxt': cxtStr } = socket.handshake.headers;
|
|
47
|
+
const context = await this.contextBuilder(cxtStr);
|
|
48
|
+
socket.userId = context.getCurrentUserId();
|
|
49
|
+
socket.context = context;
|
|
50
|
+
socket.idMap = {};
|
|
51
|
+
socket.on('sub', async (data) => {
|
|
52
|
+
try {
|
|
53
|
+
console.log('instance:', process.env.NODE_APP_INSTANCE, 'on sub', JSON.stringify(data));
|
|
54
|
+
await Promise.all(data.map(async (ele) => {
|
|
55
|
+
const { id, entity, filter } = ele;
|
|
56
|
+
// 尝试select此filter,如果失败说明权限越界
|
|
57
|
+
await context.select(entity, {
|
|
58
|
+
data: {
|
|
59
|
+
id: 1,
|
|
60
|
+
},
|
|
61
|
+
filter,
|
|
62
|
+
}, {});
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
socket.emit('error', err.toString());
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
data.forEach((ele) => {
|
|
70
|
+
const createRoomRoutine = this.formCreateRoomRoutine(ele);
|
|
71
|
+
this.ns.adapter.on('create-room', createRoomRoutine);
|
|
72
|
+
socket.join(ele.id);
|
|
73
|
+
this.ns.adapter.off('create-room', createRoomRoutine);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
socket.on('unsub', (ids) => {
|
|
77
|
+
// console.log('instance:', process.env.NODE_APP_INSTANCE, 'on unsub', JSON.stringify(ids));
|
|
78
|
+
ids.forEach((id) => {
|
|
79
|
+
socket.leave(id);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
socket.emit('error', err.toString());
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
this.ns.adapter.on('delete-room', (room) => {
|
|
88
|
+
const entity = this.idEntityMap[room];
|
|
89
|
+
if (entity) {
|
|
90
|
+
// console.log('instance:', process.env.NODE_APP_INSTANCE, 'remove filter', room);
|
|
91
|
+
(0, lodash_1.unset)(this.filterMap[entity], room);
|
|
92
|
+
(0, lodash_1.unset)(this.idEntityMap, room);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
this.ns.on('sendRecord', (entity, filter, record, isCreate) => {
|
|
96
|
+
console.log('instance:', process.env.NODE_APP_INSTANCE, 'get record from another', JSON.stringify(entity));
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
sendRecord(entity, filter, record, sid, isCreate) {
|
|
100
|
+
if (entity === 'spContractApplyment') {
|
|
101
|
+
console.log('instance:', process.env.NODE_APP_INSTANCE, 'sendRecord', JSON.stringify(entity));
|
|
102
|
+
}
|
|
103
|
+
this.ns.serverSideEmit('sendRecord', entity, filter, record, isCreate);
|
|
104
|
+
if (this.filterMap[entity]) {
|
|
105
|
+
Object.keys(this.filterMap[entity]).forEach(async (room) => {
|
|
106
|
+
const context = await this.contextBuilder();
|
|
107
|
+
const filter2 = this.filterMap[entity][room];
|
|
108
|
+
let needSend = false;
|
|
109
|
+
if (isCreate) {
|
|
110
|
+
// 如果是插入数据肯定是单行,使用相容性检测
|
|
111
|
+
const contained = await (0, oak_domain_1.checkFilterContains)(entity, context, filter2, filter, true);
|
|
112
|
+
needSend = contained;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
const repeled = await (0, oak_domain_1.checkFilterRepel)(entity, context, filter, filter2, true);
|
|
116
|
+
needSend = !repeled;
|
|
117
|
+
}
|
|
118
|
+
if (needSend) {
|
|
119
|
+
// console.log('instance:', process.env.NODE_APP_INSTANCE, 'needSend', JSON.stringify(room));
|
|
120
|
+
if (sid) {
|
|
121
|
+
this.ns.to(room).except(sid).emit('data', [record], [room]);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
this.ns.to(room).emit('data', [record], [room]);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
onDataCommited(context) {
|
|
131
|
+
const sid = context.getSubscriberId();
|
|
132
|
+
const { opRecords } = context;
|
|
133
|
+
opRecords.forEach((record) => {
|
|
134
|
+
const { a } = record;
|
|
135
|
+
switch (a) {
|
|
136
|
+
case 'c': {
|
|
137
|
+
const { e, d } = record;
|
|
138
|
+
this.sendRecord(e, d, record, sid, true);
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
case 'u': {
|
|
142
|
+
const { e, d, f } = record;
|
|
143
|
+
this.sendRecord(e, f, record, sid);
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
case 'r': {
|
|
147
|
+
const { e, f } = record;
|
|
148
|
+
this.sendRecord(e, f, record, sid);
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
default: {
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
exports.default = DataSubscriber;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getClusterInfo = void 0;
|
|
4
|
+
function getProcessEnvOption(option) {
|
|
5
|
+
if (process.env.hasOwnProperty(option)) {
|
|
6
|
+
return process.env[option];
|
|
7
|
+
}
|
|
8
|
+
const lowerCase = option.toLowerCase();
|
|
9
|
+
if (process.env.hasOwnProperty(lowerCase)) {
|
|
10
|
+
return process.env[lowerCase];
|
|
11
|
+
}
|
|
12
|
+
const upperCase = option.toUpperCase();
|
|
13
|
+
if (process.env.hasOwnProperty(upperCase)) {
|
|
14
|
+
return process.env[upperCase];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
// 初始化判定集群状态,目前支持pm2的集群信息
|
|
18
|
+
function initialize() {
|
|
19
|
+
const pmId = getProcessEnvOption('NODE_APP_INSTANCE');
|
|
20
|
+
if (pmId) {
|
|
21
|
+
const usingCluster = true;
|
|
22
|
+
const instanceId = parseInt(pmId);
|
|
23
|
+
const instanceCount = parseInt(getProcessEnvOption('instances'));
|
|
24
|
+
return {
|
|
25
|
+
usingCluster,
|
|
26
|
+
instanceCount,
|
|
27
|
+
instanceId,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
usingCluster: false,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const MyClusterInfo = initialize();
|
|
35
|
+
/**
|
|
36
|
+
* 得到当前环境的集群信息
|
|
37
|
+
*/
|
|
38
|
+
function getClusterInfo() {
|
|
39
|
+
return MyClusterInfo;
|
|
40
|
+
}
|
|
41
|
+
exports.getClusterInfo = getClusterInfo;
|
package/lib/index.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { AppLoader } from './AppLoader';
|
|
1
|
+
export { AppLoader } from './AppLoader';
|
|
2
|
+
export * from './cluster/env';
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AppLoader = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AppLoader = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
var AppLoader_1 = require("./AppLoader");
|
|
6
|
+
Object.defineProperty(exports, "AppLoader", { enumerable: true, get: function () { return AppLoader_1.AppLoader; } });
|
|
7
|
+
tslib_1.__exportStar(require("./cluster/env"), exports);
|
package/lib/polyfill.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export type GenerateIdOption = {
|
|
2
|
-
shuffle?: boolean;
|
|
3
|
-
};
|
|
1
|
+
export type GenerateIdOption = {
|
|
2
|
+
shuffle?: boolean;
|
|
3
|
+
};
|
package/package.json
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "oak-backend-base",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "oak-backend-base",
|
|
5
|
-
"main": "lib/index",
|
|
6
|
-
"author": {
|
|
7
|
-
"name": "XuChang"
|
|
8
|
-
},
|
|
9
|
-
"files": [
|
|
10
|
-
"lib/**/*"
|
|
11
|
-
],
|
|
12
|
-
"scripts": {
|
|
13
|
-
"copy-files": "copyfiles -u 1 src/**/*.json lib/",
|
|
14
|
-
"test": "ts-node test/test.ts",
|
|
15
|
-
"test2": "ts-node test/testDbStore.ts",
|
|
16
|
-
"build": "tsc && npm run copy-files"
|
|
17
|
-
},
|
|
18
|
-
"dependencies": {
|
|
19
|
-
"lodash": "^4.17.21",
|
|
20
|
-
"mysql": "^2.18.1",
|
|
21
|
-
"mysql2": "^2.3.3",
|
|
22
|
-
"node-schedule": "^2.1.0",
|
|
23
|
-
"oak-common-aspect": "^2.
|
|
24
|
-
"oak-frontend-base": "^
|
|
25
|
-
"oak-db": "^3.0.
|
|
26
|
-
"oak-domain": "^
|
|
27
|
-
"socket.io": "^4.7.2",
|
|
28
|
-
"uuid": "^8.3.2"
|
|
29
|
-
},
|
|
30
|
-
"license": "ISC",
|
|
31
|
-
"devDependencies": {
|
|
32
|
-
"@types/lodash": "^4.14.198",
|
|
33
|
-
"@types/node": "^20.6.0",
|
|
34
|
-
"@types/node-schedule": "^2.1.0",
|
|
35
|
-
"@types/uuid": "^8.3.4",
|
|
36
|
-
"copyfiles": "^2.4.1",
|
|
37
|
-
"ts-node": "^10.9.1",
|
|
38
|
-
"tslib": "^2.4.0",
|
|
39
|
-
"typescript": "^5.2.2"
|
|
40
|
-
}
|
|
41
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "oak-backend-base",
|
|
3
|
+
"version": "3.2.0",
|
|
4
|
+
"description": "oak-backend-base",
|
|
5
|
+
"main": "lib/index",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "XuChang"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"lib/**/*"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"copy-files": "copyfiles -u 1 src/**/*.json lib/",
|
|
14
|
+
"test": "ts-node test/test.ts",
|
|
15
|
+
"test2": "ts-node test/testDbStore.ts",
|
|
16
|
+
"build": "tsc && npm run copy-files"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"lodash": "^4.17.21",
|
|
20
|
+
"mysql": "^2.18.1",
|
|
21
|
+
"mysql2": "^2.3.3",
|
|
22
|
+
"node-schedule": "^2.1.0",
|
|
23
|
+
"oak-common-aspect": "^2.3.3",
|
|
24
|
+
"oak-frontend-base": "^4.0.0",
|
|
25
|
+
"oak-db": "^3.0.3",
|
|
26
|
+
"oak-domain": "^4.0.0",
|
|
27
|
+
"socket.io": "^4.7.2",
|
|
28
|
+
"uuid": "^8.3.2"
|
|
29
|
+
},
|
|
30
|
+
"license": "ISC",
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/lodash": "^4.14.198",
|
|
33
|
+
"@types/node": "^20.6.0",
|
|
34
|
+
"@types/node-schedule": "^2.1.0",
|
|
35
|
+
"@types/uuid": "^8.3.4",
|
|
36
|
+
"copyfiles": "^2.4.1",
|
|
37
|
+
"ts-node": "^10.9.1",
|
|
38
|
+
"tslib": "^2.4.0",
|
|
39
|
+
"typescript": "^5.2.2"
|
|
40
|
+
}
|
|
41
|
+
}
|