egos-transfer 0.2.5 → 0.2.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/dist/index.js CHANGED
@@ -13,808 +13,8 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
13
13
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
17
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
18
- return new (P || (P = Promise))(function (resolve, reject) {
19
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
20
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
21
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
22
- step((generator = generator.apply(thisArg, _arguments || [])).next());
23
- });
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
16
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.PeerTransfer = void 0;
30
- const constant_1 = require("./constant");
31
- const peerjs_1 = require("peerjs");
32
- const entity_1 = require("./entity");
33
- const router_1 = require("./router");
34
- const axios_1 = __importDefault(require("axios"));
35
- const delay_1 = __importDefault(require("delay"));
36
- /** 重连退避相关常量 */
37
- const MAX_RECONNECT_BACKOFF = 30000; // 最大退避 30s
38
- const BASE_RECONNECT_BACKOFF = 1000; // 基础退避 1s
39
- class PeerTransfer {
40
- constructor(deviceId, config, isRandomPeerId = false) {
41
- this.checkerId = null;
42
- /** 重连尝试次数,成功连接后归零 */
43
- this.reconnectAttempt = 0;
44
- /** 标记实例已销毁,防止异步操作继续 */
45
- this.destroyed = false;
46
- /** 按 requestId 追踪进行中的请求 */
47
- this.inRequest = new Map();
48
- this.connectPool = new Map();
49
- this.peerConfig = Object.assign(Object.assign({}, config), { key: String(Date.now()) });
50
- this.requests = new Map();
51
- this.requestTimers = new Map();
52
- this.timeout = entity_1.REQUEST_TIMEOUT;
53
- this.router = new router_1.PeerRouter();
54
- this.isPaused = false;
55
- this.peerId = isRandomPeerId ? deviceId + '_' + Date.now() : deviceId;
56
- this.deviceId = deviceId;
57
- }
58
- createPeer() {
59
- return __awaiter(this, arguments, void 0, function* (force = false) {
60
- var _a;
61
- console.log('createPeer', this.isPaused, force);
62
- if (this.isPaused && !force) {
63
- return;
64
- }
65
- if (this.booted) {
66
- return this.booted;
67
- }
68
- if (((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open) && !force) {
69
- return this.peer;
70
- }
71
- this.destroy();
72
- yield (0, delay_1.default)(1500);
73
- yield this.reloadConfig();
74
- const peer = new peerjs_1.Peer(this.peerId, Object.assign(Object.assign({}, this.peerConfig), { pingInterval: 9000 }));
75
- this.peer = peer;
76
- yield this.initialize(this.peer);
77
- this.checkConnection();
78
- this.destroyed = false;
79
- return this.peer;
80
- });
81
- }
82
- initialize(peer) {
83
- return __awaiter(this, void 0, void 0, function* () {
84
- if (this.checkerId) {
85
- clearInterval(this.checkerId);
86
- this.checkerId = null;
87
- }
88
- if (this.booted) {
89
- return this.booted;
90
- }
91
- this.booted = new Promise((resolve) => {
92
- const timer = setTimeout(() => {
93
- resolve(null);
94
- }, constant_1.PEER_OPEN_TIMEOUT);
95
- const done = (p) => {
96
- clearTimeout(timer);
97
- resolve(p);
98
- };
99
- peer.once('open', (id) => {
100
- console.log('peer@open');
101
- this.reconnectAttempt = 0; // 连接成功,重置退避计数
102
- done(peer);
103
- });
104
- // peer.on('disconnected', () => {
105
- // if (!this.isPaused) {
106
- // this.reconnect();
107
- // }
108
- // });
109
- peer.on('close', () => {
110
- setTimeout(() => {
111
- if (!this.isPaused && !this.destroyed) {
112
- this.reconnect();
113
- }
114
- }, constant_1.CONNECTION_TIMEOUT);
115
- });
116
- peer.on('error', (err) => __awaiter(this, void 0, void 0, function* () {
117
- if (err.message === constant_1.CONNECTION_PEER_CONFLICT) {
118
- this.stop();
119
- done(null);
120
- return;
121
- }
122
- if (err.message === constant_1.CONNECTION_LIMIT_EXCEED) {
123
- this.onConnectLimit();
124
- return done(null);
125
- }
126
- if (err.message === constant_1.UNAUTHORIZED) {
127
- done(null);
128
- return this.requireAuth();
129
- }
130
- if (err.message === constant_1.CONNECTION_DUPLICATED) {
131
- // 连接级重复错误,不应销毁重建 peer
132
- // createConnection 重试循环会处理
133
- console.warn('peer@error: connection duplicated, will retry');
134
- return;
135
- }
136
- if (err.type === 'network') {
137
- done(null);
138
- return this.reconnect();
139
- }
140
- if (err.type === 'server-error') {
141
- done(null);
142
- return this.reconnect();
143
- }
144
- done(null);
145
- return this.createPeer(true);
146
- }));
147
- });
148
- peer.on('connection', (conn) => {
149
- conn.label = 'incoming';
150
- this.onConnect(conn);
151
- });
152
- const socket = peer.socket;
153
- socket === null || socket === void 0 ? void 0 : socket.on('message', (message) => {
154
- this.handleSocketMessage(message);
155
- });
156
- this.onHeartbeat({ type: 'HEARTBEAT' });
157
- try {
158
- yield this.booted;
159
- }
160
- catch (_a) {
161
- // booted rejected via timer timeout
162
- }
163
- finally {
164
- this.booted = undefined;
165
- }
166
- });
167
- }
168
- handleSocketMessage(message) {
169
- if (this.isPaused) {
170
- return;
171
- }
172
- this.onOpen(message);
173
- this.onDeviceOnline(message);
174
- this.onDeviceOffline(message);
175
- this.onError(message);
176
- this.onHeartbeat(message);
177
- }
178
- onHeartbeat(message) {
179
- if (message.type !== 'HEARTBEAT' || this.isPaused) {
180
- return;
181
- }
182
- }
183
- onError(message) {
184
- var _a;
185
- if (message.type !== 'ERROR') {
186
- return;
187
- }
188
- if (((_a = message.payload) === null || _a === void 0 ? void 0 : _a.msg) === constant_1.CONNECTION_PEER_CONFLICT) {
189
- this.stop();
190
- this.getStore().dispatch({
191
- type: 'global/updateNetworkState',
192
- payload: {
193
- error: true,
194
- code: 'PEER_CONNECTION_CONFLICT',
195
- message: 'peer conflict',
196
- },
197
- });
198
- }
199
- }
200
- onOpen(message) {
201
- if (message.type !== 'OPEN') {
202
- return;
203
- }
204
- }
205
- onDeviceOnline(message) {
206
- return __awaiter(this, void 0, void 0, function* () {
207
- if (message.type !== 'ONLINE') {
208
- return;
209
- }
210
- this.online(message.payload.deviceId);
211
- });
212
- }
213
- onDeviceOffline(message) {
214
- if (message.type !== 'OFFLINE') {
215
- return;
216
- }
217
- this.ping(message.payload.deviceId);
218
- }
219
- removeConnection(peerId, connectionId) {
220
- var _a, _b, _c;
221
- const conn = this.connectPool.get(peerId);
222
- if (conn) {
223
- if (connectionId && conn.connectionId !== connectionId) {
224
- return;
225
- }
226
- this.connectPool.delete(peerId);
227
- this.handleConnectionClose(peerId, conn);
228
- conn.removeAllListeners();
229
- conn.close();
230
- (_a = this.peer) === null || _a === void 0 ? void 0 : _a._removeConnection(conn);
231
- }
232
- else {
233
- const connections = ((_b = this.peer) === null || _b === void 0 ? void 0 : _b.connections) || {};
234
- const conns = connections[peerId] || [];
235
- if (conns.length > 0) {
236
- for (const c of conns) {
237
- c.removeAllListeners();
238
- c.close();
239
- (_c = this.peer) === null || _c === void 0 ? void 0 : _c._removeConnection(c);
240
- }
241
- }
242
- }
243
- }
244
- /**
245
- * 连接关闭时尝试快速重连(5s 超时):
246
- * - 重连成功 → 保留 inRequest 条目,更新 conn 引用
247
- * - 重连失败 → 触发 feedback 并清理 inRequest
248
- */
249
- handleConnectionClose(peerId, conn) {
250
- return __awaiter(this, void 0, void 0, function* () {
251
- const matchedEntries = [];
252
- for (const [reqId, entry] of this.inRequest) {
253
- if (entry.conn.connectionId === conn.connectionId) {
254
- matchedEntries.push([reqId, entry]);
255
- }
256
- }
257
- if (matchedEntries.length === 0) {
258
- return;
259
- }
260
- // 快速重连,超时 5s
261
- const newConn = yield Promise.race([
262
- this.connectToPeer(peerId),
263
- (0, delay_1.default)(5000).then(() => undefined),
264
- ]);
265
- if (!this.isValidConnection(newConn)) {
266
- // 重连失败,触发 feedback 让请求走重试逻辑
267
- for (const [reqId, entry] of matchedEntries) {
268
- entry.feedback();
269
- this.inRequest.delete(reqId);
270
- }
271
- return;
272
- }
273
- // 重连成功,更新 inRequest 中的 conn 引用
274
- for (const [reqId, entry] of matchedEntries) {
275
- if (this.inRequest.has(reqId)) {
276
- this.inRequest.set(reqId, Object.assign(Object.assign({}, entry), { conn: newConn }));
277
- }
278
- }
279
- });
280
- }
281
- addConnection(conn) {
282
- this.connectPool.set(conn.peer, conn);
283
- const connecting = PeerTransfer.connecting.get(conn.peer);
284
- if (connecting) {
285
- connecting.resolve(conn);
286
- }
287
- }
288
- checkConnection() {
289
- if (this.checkerId) {
290
- clearInterval(this.checkerId);
291
- }
292
- this.checkerId = setInterval(() => __awaiter(this, void 0, void 0, function* () {
293
- var _a;
294
- if (!((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open)) {
295
- yield this.reconnect();
296
- }
297
- // turn credential expires
298
- if (this.peerConfig.turnExpiredAt && this.peerConfig.turnExpiredAt - 30000 < Date.now()) {
299
- yield this.reloadConfig();
300
- yield this.createPeer(true);
301
- return;
302
- }
303
- const deviceIds = Array.from(this.connectPool.keys());
304
- const pingTasks = deviceIds.map((deviceId) => __awaiter(this, void 0, void 0, function* () {
305
- const conn = this.connectPool.get(deviceId);
306
- if (!this.isValidConnection(conn)) {
307
- this.removeConnection(conn.peer, conn.connectionId);
308
- return;
309
- }
310
- const ok = yield this.ping(conn.peer);
311
- if (!ok) {
312
- this.removeConnection(conn.peer, conn.connectionId);
313
- }
314
- }));
315
- // 并行执行,不阻塞下个心跳周期
316
- yield Promise.allSettled(pingTasks);
317
- }), constant_1.HEARTBEAT_INTERVAL);
318
- }
319
- getApiHost() {
320
- var _a, _b, _c;
321
- const protocol = ((_a = this.peerConfig) === null || _a === void 0 ? void 0 : _a.secure) ? 'https' : 'http';
322
- const host = ((_b = this.peerConfig) === null || _b === void 0 ? void 0 : _b.host) || 'localhost';
323
- const port = ((_c = this.peerConfig) === null || _c === void 0 ? void 0 : _c.port) || 9000;
324
- return `${protocol}://${host}:${port}`;
325
- }
326
- getDeviceStatus(peerId) {
327
- return __awaiter(this, void 0, void 0, function* () {
328
- try {
329
- const apiHost = this.getApiHost();
330
- const res = yield axios_1.default.get(`${apiHost}/api/v1/devices/${peerId}/status`);
331
- if (res.status < 400) {
332
- return res.data.data;
333
- }
334
- }
335
- catch (err) {
336
- console.log('getDeviceStatus@error', err);
337
- }
338
- });
339
- }
340
- connectToPeer(peerId) {
341
- return __awaiter(this, void 0, void 0, function* () {
342
- if (peerId === this.deviceId) {
343
- return;
344
- }
345
- const existingConn = this.connectPool.get(peerId);
346
- console.log('connectToPeer', this.isPaused, this.connectPool.size);
347
- if (existingConn) {
348
- if (this.isValidConnection(existingConn)) {
349
- return existingConn;
350
- }
351
- else {
352
- this.removeConnection(existingConn.peer, existingConn.connectionId);
353
- }
354
- }
355
- if (PeerTransfer.connecting.has(peerId)) {
356
- const entry = PeerTransfer.connecting.get(peerId);
357
- const conn = yield (entry === null || entry === void 0 ? void 0 : entry.promise);
358
- if (conn) {
359
- return conn;
360
- }
361
- }
362
- return this.createConnection(peerId);
363
- });
364
- }
365
- createConnection(peerId) {
366
- return __awaiter(this, void 0, void 0, function* () {
367
- const q = PeerTransfer.connecting.get(peerId);
368
- if (q) {
369
- return q.promise;
370
- }
371
- let resolve;
372
- let reject;
373
- const connectionPromise = new Promise((res, rej) => {
374
- resolve = res;
375
- reject = rej;
376
- });
377
- PeerTransfer.connecting.set(peerId, { promise: connectionPromise, resolve, reject });
378
- // 兜底超时,防止 connecting 条目永远不清理
379
- const guardTimer = setTimeout(() => {
380
- PeerTransfer.connecting.delete(peerId);
381
- resolve(undefined);
382
- }, constant_1.CONNECTION_TIMEOUT * 3);
383
- const doConnect = () => __awaiter(this, void 0, void 0, function* () {
384
- var _a, _b;
385
- try {
386
- for (let retry = 0; retry < 3; retry++) {
387
- if (!this.peer) {
388
- yield this.createPeer();
389
- }
390
- if (!((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open)) {
391
- yield this.reconnect();
392
- }
393
- // 重试前检查:对方可能已经建连成功(duplicate 场景)
394
- const cur = this.connectPool.get(peerId);
395
- if (this.isValidConnection(cur)) {
396
- clearTimeout(guardTimer);
397
- return resolve(cur);
398
- }
399
- const conn = (_b = this.peer) === null || _b === void 0 ? void 0 : _b.connect(peerId, {
400
- label: 'outgoing',
401
- metadata: { time: Date.now() },
402
- });
403
- if (!conn) {
404
- continue;
405
- }
406
- const connection = yield this.onConnect(conn).catch(() => { });
407
- if (connection) {
408
- clearTimeout(guardTimer);
409
- return resolve(connection);
410
- }
411
- // duplicate 场景:onConnect 返回 undefined 但连接池可能已有对方建的连接
412
- const pooled = this.connectPool.get(peerId);
413
- if (this.isValidConnection(pooled)) {
414
- clearTimeout(guardTimer);
415
- return resolve(pooled);
416
- }
417
- }
418
- clearTimeout(guardTimer);
419
- resolve(undefined);
420
- return undefined;
421
- }
422
- catch (err) {
423
- reject(err);
424
- }
425
- finally {
426
- PeerTransfer.connecting.delete(peerId);
427
- }
428
- });
429
- doConnect();
430
- const conn = yield connectionPromise;
431
- return conn;
432
- });
433
- }
434
- /**
435
- * 心跳检测 - 直接 send,不走 request 管线,避免重试放大
436
- */
437
- ping(peerId) {
438
- return __awaiter(this, void 0, void 0, function* () {
439
- if (this.deviceId === peerId) {
440
- return;
441
- }
442
- const conn = this.connectPool.get(peerId);
443
- if (!this.isValidConnection(conn)) {
444
- this.removeConnection(peerId, conn === null || conn === void 0 ? void 0 : conn.connectionId);
445
- return;
446
- }
447
- try {
448
- const requestId = yield this.genRequestId();
449
- return new Promise((resolve) => {
450
- const timer = setTimeout(() => {
451
- this.requests.delete(requestId);
452
- resolve(false);
453
- }, constant_1.PING_TIMEOUT);
454
- this.requests.set(requestId, () => {
455
- clearTimeout(timer);
456
- resolve(true);
457
- });
458
- conn.send({
459
- route: entity_1.PeerRoutes.HEARTBEAT,
460
- method: 'get',
461
- body: {},
462
- requestId,
463
- scope: entity_1.PeerScope.REQUEST,
464
- action: entity_1.PeerAction.SEND,
465
- src: this.peerId,
466
- dest: peerId,
467
- headers: {},
468
- createdAt: Date.now(),
469
- });
470
- });
471
- }
472
- catch (_a) {
473
- return false;
474
- }
475
- });
476
- }
477
- onConnect(conn) {
478
- return __awaiter(this, void 0, void 0, function* () {
479
- if (!conn) {
480
- return;
481
- }
482
- const exists = this.connectPool.get(conn.peer);
483
- if (exists) {
484
- // 双方同时建连时,保留 peerId 字典序大的那条(确定性,不依赖时间戳)
485
- if (exists.connectionId > conn.connectionId) {
486
- this.removeConnection(conn.peer, conn.connectionId);
487
- if (this.isValidConnection(exists)) {
488
- return exists;
489
- }
490
- }
491
- else {
492
- this.removeConnection(exists.peer, exists.connectionId);
493
- }
494
- }
495
- if (conn.open) {
496
- this.addConnection(conn);
497
- this.bindConnectionData(conn);
498
- return conn;
499
- }
500
- return new Promise((resolve) => {
501
- let timer = null;
502
- const done = (connection) => {
503
- if (timer) {
504
- clearTimeout(timer);
505
- timer = null;
506
- }
507
- if (connection) {
508
- this.addConnection(connection);
509
- }
510
- resolve(connection);
511
- };
512
- timer = setTimeout(() => {
513
- if (this.isValidConnection(conn)) {
514
- this.addConnection(conn);
515
- done(conn);
516
- }
517
- else {
518
- this.removeConnection(conn.peer, conn.connectionId);
519
- done(undefined);
520
- }
521
- }, constant_1.CONNECTION_TIMEOUT);
522
- this.bindConnectionData(conn);
523
- conn.on('error', (err) => {
524
- // duplicate 场景:连接池可能已有对方建的连接,不应删除
525
- const pooled = this.connectPool.get(conn.peer);
526
- if (this.isValidConnection(pooled)) {
527
- done(pooled);
528
- return;
529
- }
530
- this.removeConnection(conn.peer, conn.connectionId);
531
- done(null);
532
- });
533
- conn.on('close', () => {
534
- console.log('close------------>', conn.label);
535
- this.removeConnection(conn.peer, conn.connectionId);
536
- done(null);
537
- });
538
- conn.on('open', () => {
539
- done(conn);
540
- });
541
- });
542
- });
543
- }
544
- /** 绑定 DataConnection 的 data 事件 */
545
- bindConnectionData(conn) {
546
- conn.on('data', (message) => {
547
- switch (message.scope) {
548
- case entity_1.PeerScope.REQUEST:
549
- return this.onRequest(conn, message);
550
- case entity_1.PeerScope.RESPONSE:
551
- return this.onResponse(conn, message);
552
- default:
553
- return this.responseFail(conn, message, 'unknown scope');
554
- }
555
- });
556
- }
557
- request(peerId, payload) {
558
- return __awaiter(this, void 0, void 0, function* () {
559
- var _a;
560
- const requestId = payload.requestId || (yield this.genRequestId());
561
- const maxRetry = 2;
562
- let res;
563
- for (let attempt = 0; attempt <= maxRetry; attempt++) {
564
- res = yield this.doRequestOnce(peerId, payload, requestId);
565
- console.log('request once', res);
566
- const code = (_a = res.error) === null || _a === void 0 ? void 0 : _a.code;
567
- if (!res.error || (code !== 'CONN_CLOSED' && code !== 'CONN_FAILED')) {
568
- return res;
569
- }
570
- }
571
- return res;
572
- });
573
- }
574
- /**
575
- * 执行一次请求,返回带错误码的结果供外层判断是否重试
576
- * @param peerId - 目标 peerId
577
- * @param payload - 请求负载
578
- * @param requestId - 请求ID(重试时复用)
579
- * @returns error.code: CONN_CLOSED/CONN_FAILED(可重试)、TIMEOUT(不重试)
580
- */
581
- doRequestOnce(peerId, payload, requestId) {
582
- return __awaiter(this, void 0, void 0, function* () {
583
- console.log('doRequestOnce@@', peerId, this.destroyed, payload.route);
584
- if (this.destroyed) {
585
- return Object.assign(Object.assign({}, payload), { body: {}, error: { message: 'destroyed', code: 'CONN_CLOSED' } });
586
- }
587
- const conn = yield this.connectToPeer(peerId);
588
- if (!this.isValidConnection(conn)) {
589
- return Object.assign(Object.assign({}, payload), { body: {}, error: { message: 'build connection failed', code: 'CONN_FAILED' } });
590
- }
591
- return new Promise((resolve) => {
592
- let timeout = null;
593
- const cleanup = () => {
594
- if (timeout) {
595
- clearTimeout(timeout);
596
- timeout = null;
597
- }
598
- this.inRequest.delete(requestId);
599
- this.requests.delete(requestId);
600
- // 清理 addRequest 可能创建的定时器
601
- const oldTimer = this.requestTimers.get(requestId);
602
- if (oldTimer) {
603
- clearTimeout(oldTimer);
604
- this.requestTimers.delete(requestId);
605
- }
606
- };
607
- timeout = setTimeout(() => {
608
- // 先清理,避免 removeConnection 触发 feedback 二次 resolve
609
- cleanup();
610
- this.removeConnection(conn.peer, conn.connectionId);
611
- resolve(Object.assign(Object.assign({}, payload), { body: {}, error: { message: 'request timeout', code: 'TIMEOUT' } }));
612
- }, payload.timeout || entity_1.REQUEST_TIMEOUT);
613
- this.inRequest.set(requestId, {
614
- conn,
615
- message: payload,
616
- feedback: () => {
617
- cleanup();
618
- resolve(Object.assign(Object.assign({}, payload), { body: {}, error: { message: 'send failed', code: 'CONN_CLOSED' } }));
619
- },
620
- });
621
- // 直接 set,避免 addRequest 内部 setTimeout 在重试时误删新回调
622
- this.requests.set(requestId, (message) => {
623
- cleanup();
624
- const now = Date.now();
625
- if (now - message.createdAt > 3000) {
626
- console.warn('[egos] slow peer request:', message.route, now - message.createdAt);
627
- }
628
- resolve(message);
629
- });
630
- this.send(conn, Object.assign(Object.assign({}, payload), { requestId, headers: Object.assign({}, payload.headers) })).catch(() => {
631
- cleanup();
632
- resolve(Object.assign(Object.assign({}, payload), { body: {}, error: { message: 'send failed', code: 'CONN_CLOSED' } }));
633
- });
634
- });
635
- });
636
- }
637
- reply(conn, oldMessage, message) {
638
- return __awaiter(this, void 0, void 0, function* () {
639
- const data = Object.assign(Object.assign(Object.assign({}, this.inheritMessage(oldMessage)), message), { dest: conn.peer, scope: entity_1.PeerScope.RESPONSE, updatedAt: Date.now() });
640
- if (!this.isValidConnection(conn)) {
641
- const connection = yield this.connectToPeer(conn.peer);
642
- return connection === null || connection === void 0 ? void 0 : connection.send(data);
643
- }
644
- return conn.send(data);
645
- });
646
- }
647
- send(conn, message) {
648
- return __awaiter(this, void 0, void 0, function* () {
649
- const internalApi = yield this.getApi(conn.peer);
650
- let connection = conn;
651
- if (!this.isValidConnection(conn)) {
652
- const con = yield this.connectToPeer(conn.peer);
653
- if (!con) {
654
- return this.responseFail(conn, message, 'send with invalid connection');
655
- }
656
- connection = con;
657
- }
658
- const requestId = message.requestId || (yield this.genRequestId());
659
- return connection.send(Object.assign(Object.assign({}, message), { requestId, headers: Object.assign(Object.assign({}, message.headers), { ['x-device-token']: internalApi === null || internalApi === void 0 ? void 0 : internalApi.token }), scope: entity_1.PeerScope.REQUEST, action: entity_1.PeerAction.SEND, src: this.peerId, dest: conn.peer, createdAt: Date.now() }), false);
660
- });
661
- }
662
- inheritMessage(receiveMsg) {
663
- return {
664
- src: this.peerId,
665
- id: receiveMsg.id,
666
- requestId: receiveMsg.requestId,
667
- route: receiveMsg.route,
668
- createdAt: receiveMsg.createdAt,
669
- action: entity_1.PeerAction.RECEIVE,
670
- };
671
- }
672
- reconnect() {
673
- return __awaiter(this, void 0, void 0, function* () {
674
- console.log('reconnect', this.isPaused);
675
- if (this.isPaused) {
676
- return;
677
- }
678
- if (this.reconnectingPromise) {
679
- return yield this.reconnectingPromise;
680
- }
681
- this.reconnectingPromise = this.doReconnect();
682
- return yield this.reconnectingPromise.finally(() => {
683
- this.reconnectingPromise = undefined;
684
- });
685
- });
686
- }
687
- isValidConnection(conn) {
688
- if (!(conn === null || conn === void 0 ? void 0 : conn.open)) {
689
- return false;
690
- }
691
- if (!(conn === null || conn === void 0 ? void 0 : conn.peerConnection)) {
692
- return false;
693
- }
694
- return ['connected', 'completed'].includes(conn.peerConnection.connectionState);
695
- }
696
- doReconnect() {
697
- return __awaiter(this, void 0, void 0, function* () {
698
- var _a, _b, _c, _d;
699
- try {
700
- if (this.isPaused) {
701
- return;
702
- }
703
- // 已连接且 token 未变,无需重连
704
- if (((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open) && this.peerConfig.token === ((_b = this.peer) === null || _b === void 0 ? void 0 : _b.options.token)) {
705
- return this.peer;
706
- }
707
- // 指数退避
708
- this.reconnectAttempt++;
709
- const backoff = Math.min(BASE_RECONNECT_BACKOFF * Math.pow(2, this.reconnectAttempt - 1), MAX_RECONNECT_BACKOFF);
710
- yield (0, delay_1.default)(backoff);
711
- yield this.reloadConfig();
712
- // 优先尝试 peer.reconnect() 轻量重连
713
- if (((_c = this.peer) === null || _c === void 0 ? void 0 : _c.disconnected) && ((_d = this.peer) === null || _d === void 0 ? void 0 : _d.options.token) === this.peerConfig.token) {
714
- this.peer.reconnect();
715
- return this.peer;
716
- }
717
- return this.createPeer();
718
- }
719
- catch (err) {
720
- return this.createPeer();
721
- }
722
- });
723
- }
724
- clearInstance() {
725
- var _a, _b;
726
- console.info('clearInstance');
727
- this.destroyed = true;
728
- PeerTransfer.connecting.clear();
729
- // 先触发所有 inRequest 的 feedback,让它们 resolve
730
- for (const [reqId, entry] of this.inRequest) {
731
- entry.feedback();
732
- }
733
- this.inRequest.clear();
734
- const peerIds = Array.from(this.connectPool.keys());
735
- for (const pId of peerIds) {
736
- this.removeConnection(pId);
737
- }
738
- this.requests.clear();
739
- for (const timer of this.requestTimers.values()) {
740
- clearTimeout(timer);
741
- }
742
- this.requestTimers.clear();
743
- (_a = this.peer) === null || _a === void 0 ? void 0 : _a.destroy();
744
- (_b = this.peer) === null || _b === void 0 ? void 0 : _b.removeAllListeners();
745
- this.booted = undefined;
746
- this.peer = undefined;
747
- if (this.checkerId) {
748
- clearInterval(this.checkerId);
749
- this.checkerId = null;
750
- }
751
- }
752
- destroy() {
753
- this.clearInstance();
754
- this.onDestroy();
755
- }
756
- onRequest(conn, message) {
757
- return __awaiter(this, void 0, void 0, function* () {
758
- var _a;
759
- try {
760
- console.log('onRequest@@', (_a = conn.peer) === null || _a === void 0 ? void 0 : _a.substring(0, 4), message.route);
761
- yield this.router.run(conn, message);
762
- }
763
- catch (err) {
764
- this.responseFail(conn, message, { message: err.message, code: err.code });
765
- }
766
- });
767
- }
768
- onResponse(conn, message) {
769
- return __awaiter(this, void 0, void 0, function* () {
770
- const cb = this.requests.get(message.requestId);
771
- if (cb) {
772
- cb.apply(this, [message]);
773
- this.requests.delete(message.requestId);
774
- }
775
- });
776
- }
777
- responseOk(conn, message) {
778
- return __awaiter(this, void 0, void 0, function* () {
779
- return this.reply(conn, message, { body: { ok: true } });
780
- });
781
- }
782
- responseFail(conn, message, err) {
783
- return __awaiter(this, void 0, void 0, function* () {
784
- return this.reply(conn, message, { body: {}, error: err || 'service error' });
785
- });
786
- }
787
- addRequest(id, cb) {
788
- // 清除已有定时器,避免重复注册时旧定时器误删新回调
789
- const oldTimer = this.requestTimers.get(id);
790
- if (oldTimer) {
791
- clearTimeout(oldTimer);
792
- }
793
- this.requests.set(id, cb);
794
- const timer = setTimeout(() => {
795
- this.requests.delete(id);
796
- this.requestTimers.delete(id);
797
- }, this.timeout);
798
- this.requestTimers.set(id, timer);
799
- }
800
- use(handler, prefix = '') {
801
- this.router.use(handler, prefix);
802
- }
803
- addRoute(route) {
804
- this.router.add(route);
805
- }
806
- stop() {
807
- this.isPaused = true;
808
- this.destroy();
809
- }
810
- resume() {
811
- this.isPaused = false;
812
- this.destroyed = false;
813
- return this.createPeer(true);
814
- }
815
- }
816
- exports.PeerTransfer = PeerTransfer;
817
- PeerTransfer.connecting = new Map();
17
+ __exportStar(require("./peer-transfer"), exports);
818
18
  __exportStar(require("./interfaces"), exports);
819
19
  __exportStar(require("./handler"), exports);
820
20
  __exportStar(require("./file-transfer"), exports);
@@ -824,3 +24,4 @@ __exportStar(require("./locker"), exports);
824
24
  __exportStar(require("./entity"), exports);
825
25
  __exportStar(require("./http-transformer"), exports);
826
26
  __exportStar(require("./http-transfer"), exports);
27
+ __exportStar(require("./connection-manager"), exports);