@hile/micro 2.0.4 → 2.0.5
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/dist/application.js +3 -1
- package/dist/registry.js +21 -7
- package/dist/server.d.ts +6 -0
- package/dist/server.js +13 -6
- package/package.json +3 -2
package/dist/application.js
CHANGED
|
@@ -85,11 +85,11 @@ export class Application extends Server {
|
|
|
85
85
|
// 这里不清理 topics 由业务方自己清理
|
|
86
86
|
// 这里也不清理 declare 和 undeclare 由业务方自己清理
|
|
87
87
|
return async () => {
|
|
88
|
+
this.stopped = true;
|
|
88
89
|
for (const fallback of this.fallbacks) {
|
|
89
90
|
fallback();
|
|
90
91
|
}
|
|
91
92
|
this.fallbacks.clear();
|
|
92
|
-
this.stopped = true;
|
|
93
93
|
if (this.reconnectTimeout) {
|
|
94
94
|
clearTimeout(this.reconnectTimeout);
|
|
95
95
|
this.reconnectTimeout = undefined;
|
|
@@ -106,6 +106,7 @@ export class Application extends Server {
|
|
|
106
106
|
clearTimeout(this.reconnectTimeout);
|
|
107
107
|
this.reconnectTimeout = setTimeout(() => {
|
|
108
108
|
this.reconnectTimeout = undefined;
|
|
109
|
+
this.logger.debug('[reconnecting] %s:%d', this._registry_address.host, this._registry_address.port);
|
|
109
110
|
void this.reconnectToRegistry().catch(() => {
|
|
110
111
|
if (this.stopped)
|
|
111
112
|
return;
|
|
@@ -141,6 +142,7 @@ export class Application extends Server {
|
|
|
141
142
|
for (const [topic, callback] of this.topics) {
|
|
142
143
|
await this.subscribe(topic, callback, true);
|
|
143
144
|
}
|
|
145
|
+
this.logger.debug('[reconnected] %s:%d', this._registry_address.host, this._registry_address.port);
|
|
144
146
|
})().finally(() => {
|
|
145
147
|
this.registryReconnectPromise = undefined;
|
|
146
148
|
});
|
package/dist/registry.js
CHANGED
|
@@ -3,6 +3,7 @@ import { homedir } from 'node:os';
|
|
|
3
3
|
import { resolve, join } from 'node:path';
|
|
4
4
|
import { existsSync, mkdirSync, readdirSync, readFileSync, watch } from 'node:fs';
|
|
5
5
|
import YAML from 'yaml';
|
|
6
|
+
import { createLogger } from '@hile/logger';
|
|
6
7
|
/** 将 `host:port` 或 `[ipv6]:port` 形式的 key 解析为地址(端口取最后一个 `:` 之后) */
|
|
7
8
|
export function parseAddressKey(key) {
|
|
8
9
|
const i = key.lastIndexOf(':');
|
|
@@ -51,7 +52,12 @@ export class Registry extends Server {
|
|
|
51
52
|
if (!existsSync(workspace)) {
|
|
52
53
|
mkdirSync(workspace, { recursive: true });
|
|
53
54
|
}
|
|
54
|
-
super('registry',
|
|
55
|
+
super('registry', {
|
|
56
|
+
logger: props.logger ?? createLogger({
|
|
57
|
+
level: 'debug',
|
|
58
|
+
pretty: process.env.NODE_ENV !== 'production',
|
|
59
|
+
}), ...props
|
|
60
|
+
});
|
|
55
61
|
this.workspace = workspace;
|
|
56
62
|
this.events.on('connect', (client, extras) => {
|
|
57
63
|
const key = client.host + ':' + client.port;
|
|
@@ -60,15 +66,20 @@ export class Registry extends Server {
|
|
|
60
66
|
this.namespaces.set(namespace, new Set());
|
|
61
67
|
}
|
|
62
68
|
this.namespaces.get(namespace).add(key);
|
|
69
|
+
this.logger.debug('[connect] %s/%s', key, namespace);
|
|
63
70
|
});
|
|
64
71
|
this.events.on('disconnect', (client, extras) => {
|
|
65
72
|
const key = client.host + ':' + client.port;
|
|
66
73
|
// 清理 topic 中的关联(不删除 topic,保留 data 供后续 subscriber 使用)
|
|
67
74
|
for (const [, { publishers, subscribers }] of this.topics) {
|
|
68
|
-
if (publishers.has(key))
|
|
75
|
+
if (publishers.has(key)) {
|
|
69
76
|
publishers.delete(key);
|
|
70
|
-
|
|
77
|
+
this.logger.debug('[delete publisher] %s', key);
|
|
78
|
+
}
|
|
79
|
+
if (subscribers.has(key)) {
|
|
71
80
|
subscribers.delete(key);
|
|
81
|
+
this.logger.debug('[delete subscriber] %s', key);
|
|
82
|
+
}
|
|
72
83
|
}
|
|
73
84
|
// 清理 namespace 中的关联
|
|
74
85
|
const namespace = extras.join('/');
|
|
@@ -76,8 +87,10 @@ export class Registry extends Server {
|
|
|
76
87
|
const keys = this.namespaces.get(namespace);
|
|
77
88
|
if (keys.has(key)) {
|
|
78
89
|
keys.delete(key);
|
|
90
|
+
this.logger.debug('[disconnect] %s/%s', key, namespace);
|
|
79
91
|
if (keys.size === 0) {
|
|
80
92
|
this.namespaces.delete(namespace);
|
|
93
|
+
this.logger.debug('[delete namespace] %s', namespace);
|
|
81
94
|
}
|
|
82
95
|
}
|
|
83
96
|
}
|
|
@@ -183,6 +196,7 @@ export class Registry extends Server {
|
|
|
183
196
|
entry.data = data.payload;
|
|
184
197
|
publishers.add(key);
|
|
185
198
|
this.publish(data.topic, data.payload);
|
|
199
|
+
this.logger.debug('[declare] %s/%s', key, data.topic);
|
|
186
200
|
return Date.now();
|
|
187
201
|
}));
|
|
188
202
|
}
|
|
@@ -197,8 +211,10 @@ export class Registry extends Server {
|
|
|
197
211
|
const i = publishers.size;
|
|
198
212
|
if (publishers.has(key)) {
|
|
199
213
|
publishers.delete(key);
|
|
214
|
+
this.logger.debug('[undeclare] %s/%s', key, data.topic);
|
|
200
215
|
if (publishers.size === 0 && subscribers.size === 0) {
|
|
201
216
|
this.topics.delete(data.topic);
|
|
217
|
+
this.logger.debug('[delete topic] %s', data.topic);
|
|
202
218
|
}
|
|
203
219
|
}
|
|
204
220
|
return i - publishers.size;
|
|
@@ -213,6 +229,7 @@ export class Registry extends Server {
|
|
|
213
229
|
const entry = this.topics.get(data.topic);
|
|
214
230
|
const subscribers = entry.subscribers;
|
|
215
231
|
subscribers.add(key);
|
|
232
|
+
this.logger.debug('[subscribe] %s/%s', key, data.topic);
|
|
216
233
|
return entry.data;
|
|
217
234
|
}));
|
|
218
235
|
}
|
|
@@ -223,14 +240,11 @@ export class Registry extends Server {
|
|
|
223
240
|
return 0;
|
|
224
241
|
const entry = this.topics.get(data.topic);
|
|
225
242
|
const subscribers = entry.subscribers;
|
|
226
|
-
const publishers = entry.publishers;
|
|
227
243
|
const i = subscribers.size;
|
|
228
244
|
if (subscribers.has(key)) {
|
|
229
245
|
subscribers.delete(key);
|
|
230
|
-
if (subscribers.size === 0 && publishers.size === 0) {
|
|
231
|
-
this.topics.delete(data.topic);
|
|
232
|
-
}
|
|
233
246
|
}
|
|
247
|
+
this.logger.debug('[unsubscribe] %s/%s', key, data.topic);
|
|
234
248
|
return i - subscribers.size;
|
|
235
249
|
}));
|
|
236
250
|
}
|
package/dist/server.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Client } from './client.js';
|
|
|
3
3
|
import { IncomingMessage } from 'http';
|
|
4
4
|
import { EventEmitter } from 'node:events';
|
|
5
5
|
import type { Duplex } from "node:stream";
|
|
6
|
+
import type { Logger } from '@hile/logger';
|
|
6
7
|
/** {@link MessageLoaderProps} 加上出站 WebSocket 宣告地址 */
|
|
7
8
|
export type MicroServerProps = MessageLoaderProps & {
|
|
8
9
|
/**
|
|
@@ -10,11 +11,16 @@ export type MicroServerProps = MessageLoaderProps & {
|
|
|
10
11
|
* 缺省使用 `getLocalIPv4()`;若仍为 `undefined`(无可用 IPv4)则构造 {@link Server} 时抛错。
|
|
11
12
|
*/
|
|
12
13
|
advertiseHost?: string;
|
|
14
|
+
/**
|
|
15
|
+
* 日志记录器
|
|
16
|
+
*/
|
|
17
|
+
logger?: Logger;
|
|
13
18
|
};
|
|
14
19
|
export declare class Server extends MessageLoader {
|
|
15
20
|
readonly namespace: string;
|
|
16
21
|
private wss?;
|
|
17
22
|
port?: number;
|
|
23
|
+
readonly logger: Logger | Console;
|
|
18
24
|
readonly clients: Map<string, Client>;
|
|
19
25
|
private readonly announceHost;
|
|
20
26
|
readonly events: EventEmitter<any>;
|
package/dist/server.js
CHANGED
|
@@ -9,6 +9,7 @@ export class Server extends MessageLoader {
|
|
|
9
9
|
namespace;
|
|
10
10
|
wss;
|
|
11
11
|
port;
|
|
12
|
+
logger;
|
|
12
13
|
clients = new Map();
|
|
13
14
|
announceHost;
|
|
14
15
|
events = new EventEmitter();
|
|
@@ -16,7 +17,7 @@ export class Server extends MessageLoader {
|
|
|
16
17
|
return this.announceHost;
|
|
17
18
|
}
|
|
18
19
|
constructor(namespace, props = {}) {
|
|
19
|
-
const { advertiseHost, ...loaderProps } = props;
|
|
20
|
+
const { advertiseHost, logger, ...loaderProps } = props;
|
|
20
21
|
super(loaderProps);
|
|
21
22
|
this.namespace = namespace;
|
|
22
23
|
const resolved = advertiseHost?.trim() || getLocalIPv4();
|
|
@@ -24,6 +25,7 @@ export class Server extends MessageLoader {
|
|
|
24
25
|
throw new Error('Unable to resolve advertise host for @hile/micro Server: pass `advertiseHost` (e.g. "127.0.0.1") in constructor options, or ensure getLocalIPv4() returns an address.');
|
|
25
26
|
}
|
|
26
27
|
this.announceHost = resolved;
|
|
28
|
+
this.logger = logger ?? console;
|
|
27
29
|
this.events.on('connect', (client, extras) => {
|
|
28
30
|
client.events.emit('connect', extras);
|
|
29
31
|
});
|
|
@@ -133,12 +135,12 @@ export class Server extends MessageLoader {
|
|
|
133
135
|
this.wss = new WebSocketServer({ noServer: true });
|
|
134
136
|
}
|
|
135
137
|
return async () => {
|
|
136
|
-
const toDispose = [...this.clients.values()];
|
|
137
|
-
for (const client of toDispose) {
|
|
138
|
-
client.dispose();
|
|
139
|
-
}
|
|
140
|
-
this.clients.clear();
|
|
141
138
|
if (this.wss) {
|
|
139
|
+
// terminate 立即销毁 socket,不等待对端 close frame
|
|
140
|
+
// 避免 graceful close 时对端无响应导致 HTTP server 无法关闭
|
|
141
|
+
for (const ws of [...this.wss.clients]) {
|
|
142
|
+
ws.terminate();
|
|
143
|
+
}
|
|
142
144
|
await new Promise((resolve, reject) => {
|
|
143
145
|
this.wss.close((err) => {
|
|
144
146
|
if (err)
|
|
@@ -147,6 +149,11 @@ export class Server extends MessageLoader {
|
|
|
147
149
|
});
|
|
148
150
|
});
|
|
149
151
|
}
|
|
152
|
+
const toDispose = [...this.clients.values()];
|
|
153
|
+
for (const client of toDispose) {
|
|
154
|
+
client.dispose();
|
|
155
|
+
}
|
|
156
|
+
this.clients.clear();
|
|
150
157
|
this.wss = undefined;
|
|
151
158
|
this.port = undefined;
|
|
152
159
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hile/micro",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -23,11 +23,12 @@
|
|
|
23
23
|
"vitest": "^4.0.18"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
+
"@hile/logger": "^2.0.1",
|
|
26
27
|
"@hile/message-loader": "^2.0.1",
|
|
27
28
|
"@hile/message-ws": "^2.0.3",
|
|
28
29
|
"internal-ip": "^9.0.0",
|
|
29
30
|
"ws": "^8.21.0",
|
|
30
31
|
"yaml": "^2.9.0"
|
|
31
32
|
},
|
|
32
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "aaa46af05d9fe0d658b4f7a8d54ad8da088a10f6"
|
|
33
34
|
}
|