oox 0.3.5 → 0.3.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.
- package/README.md +1 -1
- package/app.js +1 -7
- package/bin/cli.js +0 -5
- package/bin/proxy-require.js +1 -23
- package/bin/starter.js +9 -6
- package/config.js +30 -1
- package/context.js +58 -0
- package/index.js +6 -146
- package/keepalive-connection.js +61 -1
- package/logger.js +2 -1
- package/modules/http/index.js +4 -1
- package/modules/index.js +0 -3
- package/modules/module.js +1 -1
- package/package.json +6 -5
- package/proxy.js +30 -0
- package/registry.js +1 -1
- package/samples/index.js +1 -1
- package/samples/keepalive-connection-sample.js +46 -33
- package/types/app.d.ts +1 -7
- package/types/bin/starter.d.ts +2 -1
- package/types/config.d.ts +13 -1
- package/types/context.d.ts +30 -0
- package/types/index.d.ts +6 -52
- package/types/keepalive-connection.d.ts +12 -1
- package/types/modules/http/index.d.ts +2 -1
- package/types/modules/index.d.ts +1 -3
- package/types/modules/module.d.ts +2 -1
- package/types/proxy.d.ts +1 -0
- package/types/registry.d.ts +1 -1
- package/types/samples/index.d.ts +1 -1
- package/types/samples/keepalive-connection-sample.d.ts +23 -22
- package/utils.js +1 -1
- package/modules/socketio/adapter.js +0 -49
- package/modules/socketio/index.js +0 -23
- package/modules/socketio/server.js +0 -200
- package/modules/socketio/socket.js +0 -1
- package/modules/socketio/utils.js +0 -41
- package/types/modules/socketio/adapter.d.ts +0 -14
- package/types/modules/socketio/index.d.ts +0 -4
- package/types/modules/socketio/server.d.ts +0 -44
- package/types/modules/socketio/socket.d.ts +0 -8
- package/types/modules/socketio/utils.d.ts +0 -10
package/README.md
CHANGED
package/app.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
|
-
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
3
2
|
import { genKVMethods } from './utils.js';
|
|
4
|
-
|
|
5
|
-
export class AppContext {
|
|
6
|
-
// 请求溯源ID
|
|
7
|
-
traceId = '';
|
|
8
|
-
}
|
|
9
|
-
export const asyncStore = new AsyncLocalStorage();
|
|
3
|
+
import { asyncStore } from './context.js';
|
|
10
4
|
export const eventHub = new EventEmitter();
|
|
11
5
|
/**
|
|
12
6
|
* sourceMethods => methods
|
package/bin/cli.js
CHANGED
|
@@ -63,11 +63,6 @@ if (execFilename.endsWith('oox') || fileURLToPath(import.meta.url) === execFilen
|
|
|
63
63
|
['http.ssl.cert', 'file', 'set HTTPS certificate path'],
|
|
64
64
|
['http.ssl.key', 'file', 'set HTTPS private key path'],
|
|
65
65
|
['http.ssl.ca', 'file', 'set HTTPS CA path'],
|
|
66
|
-
['socketio', 'json/bool', 'SocketIO server options, support flat name, or set no to disable SocketIO server'],
|
|
67
|
-
['socketio.port', 'int server port'],
|
|
68
|
-
['socketio.path', 'string', 'set SocketIO server path'],
|
|
69
|
-
['socketio.origin', 'urls', 'set SocketIO server origin, support string | array<string>'],
|
|
70
|
-
['socketio.ssl', 'json', 'like http.ssl'],
|
|
71
66
|
];
|
|
72
67
|
console.log(mergeCommandParams(params_base));
|
|
73
68
|
console.log(chalk.bold('Registry:'));
|
package/bin/proxy-require.js
CHANGED
|
@@ -4,10 +4,6 @@ import * as path from 'node:path';
|
|
|
4
4
|
import * as oox from '../index.js';
|
|
5
5
|
import { Module } from 'node:module';
|
|
6
6
|
const require = createRequire(import.meta.url);
|
|
7
|
-
/**
|
|
8
|
-
* 为了不重复创建Proxy,这个对象用于保存各个RPC服务的各个属性Proxy
|
|
9
|
-
*/
|
|
10
|
-
const rpcServiceAttrMap = Object.create(null);
|
|
11
7
|
/**
|
|
12
8
|
* 重写 require 缓存
|
|
13
9
|
*/
|
|
@@ -24,24 +20,6 @@ function rewriteModuleCache(id, exports) {
|
|
|
24
20
|
m.paths = paths;
|
|
25
21
|
require.cache[id] = m;
|
|
26
22
|
}
|
|
27
|
-
function dotCall(name, action) {
|
|
28
|
-
return new Proxy(function () { }, {
|
|
29
|
-
get(target, key) {
|
|
30
|
-
const attrKey = name + '.' + (action ? action + '.' + key : key);
|
|
31
|
-
if (rpcServiceAttrMap) {
|
|
32
|
-
// 不重复创建Proxy
|
|
33
|
-
return rpcServiceAttrMap[attrKey];
|
|
34
|
-
}
|
|
35
|
-
const attrProxy = dotCall(name, attrKey);
|
|
36
|
-
rpcServiceAttrMap[attrKey] = attrProxy;
|
|
37
|
-
return attrProxy;
|
|
38
|
-
},
|
|
39
|
-
has(target, key) { return true; },
|
|
40
|
-
apply(target, thisArg, args) {
|
|
41
|
-
return oox.rpc(name, action, args);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
23
|
export function proxyGroup(groupDirectory, excludes = []) {
|
|
46
24
|
if (!groupDirectory)
|
|
47
25
|
return;
|
|
@@ -70,7 +48,7 @@ export function proxyGroup(groupDirectory, excludes = []) {
|
|
|
70
48
|
name = scriptMatch[1];
|
|
71
49
|
}
|
|
72
50
|
if (!excludes.includes(name))
|
|
73
|
-
rewriteModuleCache(id,
|
|
51
|
+
rewriteModuleCache(id, oox.proxy(name));
|
|
74
52
|
}
|
|
75
53
|
}
|
|
76
54
|
/**
|
package/bin/starter.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import {
|
|
3
|
+
import { configFormatters } from '../config.js';
|
|
4
4
|
import * as oox from '../index.js';
|
|
5
5
|
import { buildConfig } from './configurer.js';
|
|
6
6
|
import { registry } from './register.js';
|
|
@@ -57,13 +57,16 @@ export async function startup() {
|
|
|
57
57
|
// 服务启动
|
|
58
58
|
await oox.serve();
|
|
59
59
|
oox.emit('app:served');
|
|
60
|
-
const { http
|
|
60
|
+
const { http } = oox.modules.builtins;
|
|
61
61
|
console.log();
|
|
62
62
|
console.log('Service', chalk.bold(`${oox.config.name}`), 'running.');
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
// 打包服务地址
|
|
64
|
+
const maxNameLength = Math.max(...oox.modules.queue.map(module => module.name.length));
|
|
65
|
+
for (const module of oox.modules.queue) {
|
|
66
|
+
const spaces = ' '.repeat(Math.max(0, maxNameLength - module.name.length));
|
|
67
|
+
if (module.config.enabled && module.serviceURL)
|
|
68
|
+
console.log(` ${spaces}${chalk.bold(module.name)} at`, chalk.underline.green(module.serviceURL.toString()));
|
|
69
|
+
}
|
|
67
70
|
console.log();
|
|
68
71
|
// 服务注册
|
|
69
72
|
if (config.registry)
|
package/config.js
CHANGED
|
@@ -43,7 +43,7 @@ export class Config {
|
|
|
43
43
|
caller: [],
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
|
-
export const
|
|
46
|
+
export const configFormatters = {
|
|
47
47
|
id: function (value) {
|
|
48
48
|
return String(value || randomUUID());
|
|
49
49
|
},
|
|
@@ -114,3 +114,32 @@ export const formatters = {
|
|
|
114
114
|
return value;
|
|
115
115
|
}
|
|
116
116
|
};
|
|
117
|
+
/**
|
|
118
|
+
* 检查连接是否被允许
|
|
119
|
+
* @param ip 连接主机 IP
|
|
120
|
+
* @param caller 连接服务名称
|
|
121
|
+
* @param token 令牌
|
|
122
|
+
* @returns 是否被允许
|
|
123
|
+
*/
|
|
124
|
+
export function checkAllow(ip, caller, token) {
|
|
125
|
+
// check trusted token
|
|
126
|
+
const trusted = !config.token || token === config.token;
|
|
127
|
+
if (!trusted) {
|
|
128
|
+
const { allow } = config;
|
|
129
|
+
if (!allow.untrusted) {
|
|
130
|
+
return { allow: false, reason: 'untrusted' };
|
|
131
|
+
}
|
|
132
|
+
if (Array.isArray(allow.ip) && allow.ip.length) {
|
|
133
|
+
let allowed = allow.ip.some(item => item === '*' || new RegExp(item).test(ip));
|
|
134
|
+
if (!allowed)
|
|
135
|
+
return { allow: false, reason: 'not allow ip=' + ip };
|
|
136
|
+
}
|
|
137
|
+
if (Array.isArray(allow.caller) && allow.caller.length) {
|
|
138
|
+
let allowed = allow.caller.some(item => item === '*' || new RegExp(item).test(caller));
|
|
139
|
+
if (!allowed)
|
|
140
|
+
return { allow: false, reason: 'not allow caller=' + caller };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return { allow: true };
|
|
144
|
+
}
|
|
145
|
+
export const config = new Config();
|
package/context.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
3
|
+
export const asyncStore = new AsyncLocalStorage();
|
|
4
|
+
export class AppContext {
|
|
5
|
+
// 请求溯源ID
|
|
6
|
+
traceId = '';
|
|
7
|
+
}
|
|
8
|
+
export class Context extends AppContext {
|
|
9
|
+
// 请求溯源IP
|
|
10
|
+
sourceIP = '';
|
|
11
|
+
// 请求者IP
|
|
12
|
+
ip = '';
|
|
13
|
+
// 请求者名称
|
|
14
|
+
caller = 'anonymous';
|
|
15
|
+
// 请求者ID (长连接专用)
|
|
16
|
+
callerId = '';
|
|
17
|
+
// 请求者连接把柄
|
|
18
|
+
connection;
|
|
19
|
+
constructor(context) {
|
|
20
|
+
super();
|
|
21
|
+
if (context) {
|
|
22
|
+
if ('toJSON' in context && typeof context.toJSON !== 'function') {
|
|
23
|
+
throw new Error('Context.toJSON must be a function');
|
|
24
|
+
}
|
|
25
|
+
Object.assign(this, context);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
toJSON() {
|
|
29
|
+
const context = Object.assign({}, this);
|
|
30
|
+
delete context.connection;
|
|
31
|
+
return context;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
let genTraceIdFunction = () => randomUUID();
|
|
35
|
+
export function setGenTraceIdFunction(fn) {
|
|
36
|
+
genTraceIdFunction = fn;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 生成随机不重复id
|
|
40
|
+
*/
|
|
41
|
+
export function genTraceId() {
|
|
42
|
+
return genTraceIdFunction();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 获取链路跟踪上下文
|
|
46
|
+
*/
|
|
47
|
+
export function genContext(context) {
|
|
48
|
+
const newContext = new Context(context);
|
|
49
|
+
if (!newContext.traceId)
|
|
50
|
+
newContext.traceId = genTraceId();
|
|
51
|
+
if (!newContext.sourceIP)
|
|
52
|
+
newContext.sourceIP = newContext.ip;
|
|
53
|
+
return newContext;
|
|
54
|
+
}
|
|
55
|
+
export function getContext() {
|
|
56
|
+
const context = asyncStore.getStore();
|
|
57
|
+
return context || genContext();
|
|
58
|
+
}
|
package/index.js
CHANGED
|
@@ -1,61 +1,3 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { asyncStore, AppContext, } from './app.js';
|
|
3
|
-
import * as registry from './registry.js';
|
|
4
|
-
import { Config } from './config.js';
|
|
5
|
-
import Module from './modules/module.js';
|
|
6
|
-
import { KeepAliveConnection, keepAliveConnections, enabledKeepAliveConnections, KeepAliveConnectionError, } from './keepalive-connection.js';
|
|
7
|
-
export class Context extends AppContext {
|
|
8
|
-
// 请求溯源IP
|
|
9
|
-
sourceIP = '';
|
|
10
|
-
// 请求者IP
|
|
11
|
-
ip = '';
|
|
12
|
-
// 请求者名称
|
|
13
|
-
caller = 'anonymous';
|
|
14
|
-
// 请求者ID (长连接专用)
|
|
15
|
-
callerId = '';
|
|
16
|
-
// 请求者连接把柄
|
|
17
|
-
connection;
|
|
18
|
-
constructor(context) {
|
|
19
|
-
super();
|
|
20
|
-
if (context) {
|
|
21
|
-
if ('toJSON' in context && typeof context.toJSON !== 'function') {
|
|
22
|
-
throw new Error('Context.toJSON must be a function');
|
|
23
|
-
}
|
|
24
|
-
Object.assign(this, context);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
toJSON() {
|
|
28
|
-
const context = Object.assign({}, this);
|
|
29
|
-
delete context.connection;
|
|
30
|
-
return context;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
export const config = new Config();
|
|
34
|
-
let genTraceIdFunction = () => randomUUID();
|
|
35
|
-
export function setGenTraceIdFunction(fn) {
|
|
36
|
-
genTraceIdFunction = fn;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* 生成随机不重复id
|
|
40
|
-
*/
|
|
41
|
-
export function genTraceId() {
|
|
42
|
-
return genTraceIdFunction();
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* 获取链路跟踪上下文
|
|
46
|
-
*/
|
|
47
|
-
export function genContext(context) {
|
|
48
|
-
const newContext = new Context(context);
|
|
49
|
-
if (!newContext.traceId)
|
|
50
|
-
newContext.traceId = genTraceId();
|
|
51
|
-
if (!newContext.sourceIP)
|
|
52
|
-
newContext.sourceIP = newContext.ip;
|
|
53
|
-
return newContext;
|
|
54
|
-
}
|
|
55
|
-
export function getContext() {
|
|
56
|
-
const context = asyncStore.getStore();
|
|
57
|
-
return context || genContext();
|
|
58
|
-
}
|
|
59
1
|
export async function serve() {
|
|
60
2
|
await modules.serve();
|
|
61
3
|
registry.startBroadcastTimer();
|
|
@@ -64,96 +6,14 @@ export async function stop() {
|
|
|
64
6
|
await modules.stop();
|
|
65
7
|
registry.stopBroadcastTimer();
|
|
66
8
|
}
|
|
67
|
-
/**
|
|
68
|
-
* 检查连接是否被允许
|
|
69
|
-
* @param ip 连接主机 IP
|
|
70
|
-
* @param caller 连接服务名称
|
|
71
|
-
* @param token 令牌
|
|
72
|
-
* @returns 是否被允许
|
|
73
|
-
*/
|
|
74
|
-
export function checkAllow(ip, caller, token) {
|
|
75
|
-
// check trusted token
|
|
76
|
-
const trusted = !config.token || token === config.token;
|
|
77
|
-
if (!trusted) {
|
|
78
|
-
const { allow } = config;
|
|
79
|
-
if (!allow.untrusted) {
|
|
80
|
-
return { allow: false, reason: 'untrusted' };
|
|
81
|
-
}
|
|
82
|
-
if (Array.isArray(allow.ip) && allow.ip.length) {
|
|
83
|
-
let allowed = allow.ip.some(item => item === '*' || new RegExp(item).test(ip));
|
|
84
|
-
if (!allowed)
|
|
85
|
-
return { allow: false, reason: 'not allow ip=' + ip };
|
|
86
|
-
}
|
|
87
|
-
if (Array.isArray(allow.caller) && allow.caller.length) {
|
|
88
|
-
let allowed = allow.caller.some(item => item === '*' || new RegExp(item).test(caller));
|
|
89
|
-
if (!allowed)
|
|
90
|
-
return { allow: false, reason: 'not allow caller=' + caller };
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return { allow: true };
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* 添加长连接
|
|
97
|
-
* @throws {KeepAliveConnectionError} 连接已存在
|
|
98
|
-
* @param connection
|
|
99
|
-
*/
|
|
100
|
-
export function addKeepAliveConnection(connection) {
|
|
101
|
-
if (keepAliveConnections.has(connection.data.name, connection.data.id)) {
|
|
102
|
-
connection.disconnect();
|
|
103
|
-
throw new KeepAliveConnectionError('Connection already exists', connection);
|
|
104
|
-
}
|
|
105
|
-
keepAliveConnections.add(connection);
|
|
106
|
-
}
|
|
107
|
-
export function removeKeepAliveConnection(arg1, arg2) {
|
|
108
|
-
if (typeof arg1 === 'string') {
|
|
109
|
-
const connection = keepAliveConnections.get(arg1, arg2);
|
|
110
|
-
if (connection)
|
|
111
|
-
connection.disconnect();
|
|
112
|
-
keepAliveConnections.remove(arg1, arg2);
|
|
113
|
-
enabledKeepAliveConnections.remove(arg1, arg2);
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
arg1.disconnect();
|
|
117
|
-
keepAliveConnections.remove(arg1);
|
|
118
|
-
enabledKeepAliveConnections.remove(arg1);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* random connection select for default load balance policy
|
|
123
|
-
* @param name service name
|
|
124
|
-
* @returns selected connection
|
|
125
|
-
*/
|
|
126
|
-
let loadBalancePolicy = (name) => {
|
|
127
|
-
const connections = enabledKeepAliveConnections.getConnectionsOfService(name);
|
|
128
|
-
if (!connections || !connections.size)
|
|
129
|
-
return null;
|
|
130
|
-
const arrayConnections = Array.from(connections.values());
|
|
131
|
-
const index = Math.floor(Math.random() * arrayConnections.length);
|
|
132
|
-
return arrayConnections[index];
|
|
133
|
-
};
|
|
134
|
-
export function setLoadBalancePolicy(policy) {
|
|
135
|
-
loadBalancePolicy = policy;
|
|
136
|
-
}
|
|
137
|
-
export async function rpc(arg1, action, params, context) {
|
|
138
|
-
if (!context || !context.traceId) {
|
|
139
|
-
context = getContext();
|
|
140
|
-
}
|
|
141
|
-
let connection = null;
|
|
142
|
-
if (arg1 instanceof KeepAliveConnection) {
|
|
143
|
-
connection = arg1;
|
|
144
|
-
}
|
|
145
|
-
else if ('string' === typeof arg1) {
|
|
146
|
-
connection = loadBalancePolicy(arg1);
|
|
147
|
-
}
|
|
148
|
-
else
|
|
149
|
-
throw new Error(`Unknown rpc arg1<${arg1}>`);
|
|
150
|
-
if (!connection)
|
|
151
|
-
throw new Error(`Connection<${arg1}> not found`);
|
|
152
|
-
return connection.adapter.rpc(connection, action, params, context);
|
|
153
|
-
}
|
|
154
9
|
export * from './app.js';
|
|
10
|
+
export * from './config.js';
|
|
11
|
+
export * from './context.js';
|
|
155
12
|
export * from './keepalive-connection.js';
|
|
156
|
-
export
|
|
13
|
+
export * from './modules/module.js';
|
|
14
|
+
export * as logger from './logger.js';
|
|
15
|
+
export * from './proxy.js';
|
|
16
|
+
import * as registry from './registry.js';
|
|
157
17
|
export { registry };
|
|
158
18
|
// 放在最后导入,避免循环依赖问题
|
|
159
19
|
import * as modules from './modules/index.js';
|
package/keepalive-connection.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import EventEmitter from 'node:events';
|
|
2
|
+
import { getContext } from './context.js';
|
|
2
3
|
export class KeepAliveConnectionError extends Error {
|
|
3
4
|
connection;
|
|
4
5
|
constructor(message, connection) {
|
|
@@ -29,13 +30,13 @@ export class KeepAliveConnection extends EventEmitter {
|
|
|
29
30
|
set enabled(enabled) {
|
|
30
31
|
if (enabled !== this.#enabled) {
|
|
31
32
|
this.#enabled = enabled;
|
|
32
|
-
this.emit(enabled ? 'enabled' : 'disabled');
|
|
33
33
|
if (enabled) {
|
|
34
34
|
enabledKeepAliveConnections.add(this);
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
37
37
|
enabledKeepAliveConnections.remove(this);
|
|
38
38
|
}
|
|
39
|
+
this.emit(enabled ? 'enabled' : 'disabled');
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
get enabled() {
|
|
@@ -104,6 +105,65 @@ export class KeepAliveConnectionStore {
|
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* 添加长连接
|
|
110
|
+
* @throws {KeepAliveConnectionError} 连接已存在
|
|
111
|
+
* @param connection
|
|
112
|
+
*/
|
|
113
|
+
export function addKeepAliveConnection(connection) {
|
|
114
|
+
if (keepAliveConnections.has(connection.data.name, connection.data.id)) {
|
|
115
|
+
connection.disconnect();
|
|
116
|
+
throw new KeepAliveConnectionError('Connection already exists', connection);
|
|
117
|
+
}
|
|
118
|
+
keepAliveConnections.add(connection);
|
|
119
|
+
}
|
|
120
|
+
export function removeKeepAliveConnection(arg1, arg2) {
|
|
121
|
+
if (typeof arg1 === 'string') {
|
|
122
|
+
const connection = keepAliveConnections.get(arg1, arg2);
|
|
123
|
+
keepAliveConnections.remove(arg1, arg2);
|
|
124
|
+
enabledKeepAliveConnections.remove(arg1, arg2);
|
|
125
|
+
if (connection)
|
|
126
|
+
connection.disconnect();
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
keepAliveConnections.remove(arg1);
|
|
130
|
+
enabledKeepAliveConnections.remove(arg1);
|
|
131
|
+
arg1.disconnect();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* random connection select for default load balance policy
|
|
136
|
+
* @param name service name
|
|
137
|
+
* @returns selected connection
|
|
138
|
+
*/
|
|
139
|
+
let loadBalancePolicy = (name) => {
|
|
140
|
+
const connections = enabledKeepAliveConnections.getConnectionsOfService(name);
|
|
141
|
+
if (!connections || !connections.size)
|
|
142
|
+
return null;
|
|
143
|
+
const arrayConnections = Array.from(connections.values());
|
|
144
|
+
const index = Math.floor(Math.random() * arrayConnections.length);
|
|
145
|
+
return arrayConnections[index];
|
|
146
|
+
};
|
|
147
|
+
export function setLoadBalancePolicy(policy) {
|
|
148
|
+
loadBalancePolicy = policy;
|
|
149
|
+
}
|
|
150
|
+
export async function rpc(arg1, action, params, context) {
|
|
151
|
+
if (!context || !context.traceId) {
|
|
152
|
+
context = getContext();
|
|
153
|
+
}
|
|
154
|
+
let connection = null;
|
|
155
|
+
if (arg1 instanceof KeepAliveConnection) {
|
|
156
|
+
connection = arg1;
|
|
157
|
+
}
|
|
158
|
+
else if ('string' === typeof arg1) {
|
|
159
|
+
connection = loadBalancePolicy(arg1);
|
|
160
|
+
}
|
|
161
|
+
else
|
|
162
|
+
throw new Error(`Unknown rpc arg1<${arg1}>`);
|
|
163
|
+
if (!connection)
|
|
164
|
+
throw new Error(`Connection<${arg1}> not found`);
|
|
165
|
+
return connection.adapter.rpc(connection, action, params, context);
|
|
166
|
+
}
|
|
107
167
|
export const keepAliveConnectionAdapters = new Map();
|
|
108
168
|
export const keepAliveConnections = new KeepAliveConnectionStore();
|
|
109
169
|
export const enabledKeepAliveConnections = new KeepAliveConnectionStore();
|
package/logger.js
CHANGED
package/modules/http/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import * as https from 'node:https';
|
|
|
3
3
|
import { parseHTTPBody } from './utils.js';
|
|
4
4
|
import Router from './router.js';
|
|
5
5
|
import * as oox from '../../index.js';
|
|
6
|
-
import Module from '../module.js';
|
|
6
|
+
import { Module } from '../module.js';
|
|
7
7
|
export class HTTPConfig {
|
|
8
8
|
enabled = true;
|
|
9
9
|
// listen port
|
|
@@ -72,6 +72,9 @@ export default class HTTPModule extends Module {
|
|
|
72
72
|
getConfig() {
|
|
73
73
|
return this.config;
|
|
74
74
|
}
|
|
75
|
+
get serviceURL() {
|
|
76
|
+
return this.getURL();
|
|
77
|
+
}
|
|
75
78
|
/**
|
|
76
79
|
* start http service
|
|
77
80
|
*/
|
package/modules/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import HTTP from './http/index.js';
|
|
2
|
-
import SocketIO from './socketio/index.js';
|
|
3
2
|
/**
|
|
4
3
|
* FIFO queue for modules starting
|
|
5
4
|
*/
|
|
@@ -84,7 +83,5 @@ export async function stop() {
|
|
|
84
83
|
*/
|
|
85
84
|
export const builtins = {
|
|
86
85
|
http: new HTTP,
|
|
87
|
-
socketio: new SocketIO,
|
|
88
86
|
};
|
|
89
87
|
add(builtins.http);
|
|
90
|
-
add(builtins.socketio);
|
package/modules/module.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export class Module {
|
|
2
2
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oox",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"description": "OOX Service Engine",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"http",
|
|
@@ -24,7 +24,10 @@
|
|
|
24
24
|
"types": "./types/index.d.ts"
|
|
25
25
|
},
|
|
26
26
|
"./loader": "./bin/loader.mjs",
|
|
27
|
-
"./cli":
|
|
27
|
+
"./cli": {
|
|
28
|
+
"default": "./bin/cli.js",
|
|
29
|
+
"types": "./types/bin/cli.d.ts"
|
|
30
|
+
},
|
|
28
31
|
"./samples": {
|
|
29
32
|
"types": "./types/samples/index.d.ts",
|
|
30
33
|
"default": "./samples/index.js"
|
|
@@ -37,9 +40,7 @@
|
|
|
37
40
|
"homepage": "https://gitee.com/lipingruan/oox",
|
|
38
41
|
"license": "MIT",
|
|
39
42
|
"dependencies": {
|
|
40
|
-
"chalk": "^5.6.2"
|
|
41
|
-
"socket.io": "^4.8.3",
|
|
42
|
-
"socket.io-client": "^4.8.3"
|
|
43
|
+
"chalk": "^5.6.2"
|
|
43
44
|
},
|
|
44
45
|
"engines": {
|
|
45
46
|
"node": ">=18.0.0"
|
package/proxy.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { rpc } from './keepalive-connection.js';
|
|
2
|
+
/**
|
|
3
|
+
* 为了不重复创建Proxy,这个对象用于保存各个RPC服务的各个属性Proxy
|
|
4
|
+
*/
|
|
5
|
+
const rpcServiceAttrMap = Object.create(null);
|
|
6
|
+
export function proxy(name, action = '') {
|
|
7
|
+
return new Proxy(function () { }, {
|
|
8
|
+
get(target, key) {
|
|
9
|
+
if (typeof key !== 'string')
|
|
10
|
+
return undefined;
|
|
11
|
+
const attrKey = action ? action + '.' + key : key;
|
|
12
|
+
const attrKeyPath = name + '.' + attrKey;
|
|
13
|
+
if (attrKeyPath in rpcServiceAttrMap) {
|
|
14
|
+
// 不重复创建Proxy
|
|
15
|
+
return rpcServiceAttrMap[attrKeyPath];
|
|
16
|
+
}
|
|
17
|
+
const attrProxy = proxy(name, attrKey);
|
|
18
|
+
rpcServiceAttrMap[attrKeyPath] = attrProxy;
|
|
19
|
+
return attrProxy;
|
|
20
|
+
},
|
|
21
|
+
has(target, key) {
|
|
22
|
+
if (typeof key !== 'string')
|
|
23
|
+
return false;
|
|
24
|
+
return true;
|
|
25
|
+
},
|
|
26
|
+
apply(target, thisArg, args) {
|
|
27
|
+
return rpc(name, action, args);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
package/registry.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { config } from './
|
|
1
|
+
import { config } from './config.js';
|
|
2
2
|
import { enabledKeepAliveConnections, keepAliveConnectionAdapters, keepAliveConnections } from './keepalive-connection.js';
|
|
3
3
|
const unsubscribeListeners = new Map();
|
|
4
4
|
const subscribes = new Map();
|
package/samples/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from './keepalive-connection-sample.js';
|