egos-transfer 0.2.7 → 0.2.8

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.
@@ -81,25 +81,26 @@ class ConnectionManager {
81
81
  return conn;
82
82
  }
83
83
  remove(peerId, connectionId) {
84
- var _a, _b;
84
+ var _a, _b, _c, _d, _e;
85
85
  const conn = this.pool.get(peerId);
86
86
  if (conn) {
87
87
  if (connectionId && conn.connectionId !== connectionId)
88
88
  return;
89
89
  this.pool.delete(peerId);
90
- // 清理 connectionstatechange listener
91
- // (conn as any).__cm_stateChangeCleanup?.();
92
- // conn.removeAllListeners();
93
- // conn.close();
94
- // this.deps.getPeer()?._removeConnection(conn);
90
+ // close 触发 close 事件(handleConnClosed 会结算 in-flight 请求),
91
+ // 再清理监听器与 PeerJS 内部引用,避免僵尸连接堆积导致无法建立新连接
92
+ conn.close();
93
+ (_b = (_a = conn).__cm_stateChangeCleanup) === null || _b === void 0 ? void 0 : _b.call(_a);
94
+ conn.removeAllListeners();
95
+ (_c = this.deps.getPeer()) === null || _c === void 0 ? void 0 : _c._removeConnection(conn);
95
96
  }
96
97
  else {
97
98
  // 清理 Peer 内部残留的 connection 引用
98
- const connections = ((_a = this.deps.getPeer()) === null || _a === void 0 ? void 0 : _a.connections) || {};
99
+ const connections = ((_d = this.deps.getPeer()) === null || _d === void 0 ? void 0 : _d.connections) || {};
99
100
  for (const c of connections[peerId] || []) {
100
101
  c.removeAllListeners();
101
102
  c.close();
102
- (_b = this.deps.getPeer()) === null || _b === void 0 ? void 0 : _b._removeConnection(c);
103
+ (_e = this.deps.getPeer()) === null || _e === void 0 ? void 0 : _e._removeConnection(c);
103
104
  }
104
105
  }
105
106
  }
@@ -111,7 +112,10 @@ class ConnectionManager {
111
112
  return ['connected', 'completed'].includes(conn.peerConnection.connectionState);
112
113
  }
113
114
  handleConnClosed(conn) {
115
+ var _a;
114
116
  this.pool.delete(conn.peer);
117
+ // 同步移除 PeerJS 内部引用,避免僵尸连接堆积
118
+ (_a = this.deps.getPeer()) === null || _a === void 0 ? void 0 : _a._removeConnection(conn);
115
119
  this.deps.onConnClosed(conn);
116
120
  }
117
121
  // ── Health check ─────────────────────────────────────────────────
@@ -90,5 +90,6 @@ export declare abstract class PeerTransfer {
90
90
  */
91
91
  stop(): void;
92
92
  private destroyPeer;
93
+ askReload(peerId: string): void;
93
94
  }
94
95
  export {};
@@ -55,10 +55,9 @@ class PeerTransfer {
55
55
  // ── Peer lifecycle ──────────────────────────────────────────────
56
56
  createPeer(force) {
57
57
  return __awaiter(this, void 0, void 0, function* () {
58
- var _a, _b;
59
- console.info('createPeer##', (_a = this.peer) === null || _a === void 0 ? void 0 : _a.open, force);
58
+ var _a;
60
59
  this._exited = false;
61
- if (((_b = this.peer) === null || _b === void 0 ? void 0 : _b.open) && !force) {
60
+ if (((_a = this.peer) === null || _a === void 0 ? void 0 : _a.open) && !force) {
62
61
  return this.peer;
63
62
  }
64
63
  this.destroyPeer();
@@ -68,7 +67,13 @@ class PeerTransfer {
68
67
  yield this.waitForOpen(peer);
69
68
  this.destroyed = false;
70
69
  peer.on('close', () => {
71
- setTimeout(() => this.destroyed && this.reconnect(), exports.PEER_CLOSE_RECONNECT_TIMEOUT);
70
+ // 仅当 Peer 非主动销毁(stop/clearInstance/重建)时才重连
71
+ setTimeout(() => {
72
+ if (this.destroyed || this._exited) {
73
+ return;
74
+ }
75
+ this.reconnect();
76
+ }, exports.PEER_CLOSE_RECONNECT_TIMEOUT);
72
77
  });
73
78
  peer.on('error', (err) => {
74
79
  // 覆盖所有与 signaling server 断连相关的错误类型
@@ -88,6 +93,10 @@ class PeerTransfer {
88
93
  socket === null || socket === void 0 ? void 0 : socket.on('message', (message) => {
89
94
  this.handleSocketMessage(message);
90
95
  });
96
+ // signaling socket 断开时主动重连(兜底:部分场景不触发 peer error)
97
+ socket === null || socket === void 0 ? void 0 : socket.on('disconnected', () => {
98
+ this.reconnect();
99
+ });
91
100
  // 启动连接健康检查
92
101
  this.connectionManager.startHealthCheck();
93
102
  // 启动空闲重连定时器
@@ -144,6 +153,9 @@ class PeerTransfer {
144
153
  case 'HEARTBEAT':
145
154
  this.resetHeartbeatTimer();
146
155
  break;
156
+ case 'RELOAD':
157
+ this.reconnect(true);
158
+ break;
147
159
  case 'ERROR':
148
160
  if (((_a = message.payload) === null || _a === void 0 ? void 0 : _a.msg) === constant_1.CONNECTION_PEER_CONFLICT) {
149
161
  this.getStore().dispatch({
@@ -152,6 +164,9 @@ class PeerTransfer {
152
164
  });
153
165
  }
154
166
  break;
167
+ default:
168
+ console.log('unknown socket message type', message);
169
+ break;
155
170
  }
156
171
  }
157
172
  // ── Connection management ───────────────────────────────────────
@@ -257,13 +272,6 @@ class PeerTransfer {
257
272
  onConnClosed(conn) {
258
273
  const reqIds = this.connRequests.get(conn.connectionId);
259
274
  if (reqIds) {
260
- // for (const reqId of reqIds) {
261
- // const cb = this.requests.get(reqId);
262
- // if (cb) {
263
- // cb({ error: { message: 'connection closed', code: 'CONN_CLOSED' } } as any);
264
- // this.requests.delete(reqId);
265
- // }
266
- // }
267
275
  this.connRequests.delete(conn.connectionId);
268
276
  }
269
277
  }
@@ -561,5 +569,16 @@ class PeerTransfer {
561
569
  (_b = this.peer) === null || _b === void 0 ? void 0 : _b.removeAllListeners();
562
570
  this.peer = undefined;
563
571
  }
572
+ askReload(peerId) {
573
+ var _a;
574
+ (_a = this.peer) === null || _a === void 0 ? void 0 : _a.socket.send({
575
+ type: 'RELOAD',
576
+ payload: {
577
+ type: 'RELOAD',
578
+ src: this.peerId,
579
+ dst: peerId,
580
+ },
581
+ });
582
+ }
564
583
  }
565
584
  exports.PeerTransfer = PeerTransfer;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "egos-transfer",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "1234",
5
5
  "homepage": "https://github.com/superbogy/peer-transfer#readme",
6
6
  "bugs": {
@@ -103,11 +103,12 @@ export class ConnectionManager {
103
103
  if (conn) {
104
104
  if (connectionId && conn.connectionId !== connectionId) return;
105
105
  this.pool.delete(peerId);
106
- // 清理 connectionstatechange listener
107
- // (conn as any).__cm_stateChangeCleanup?.();
108
- // conn.removeAllListeners();
109
- // conn.close();
110
- // this.deps.getPeer()?._removeConnection(conn);
106
+ // close 触发 close 事件(handleConnClosed 会结算 in-flight 请求),
107
+ // 再清理监听器与 PeerJS 内部引用,避免僵尸连接堆积导致无法建立新连接
108
+ conn.close();
109
+ (conn as any).__cm_stateChangeCleanup?.();
110
+ conn.removeAllListeners();
111
+ this.deps.getPeer()?._removeConnection(conn);
111
112
  } else {
112
113
  // 清理 Peer 内部残留的 connection 引用
113
114
  const connections = this.deps.getPeer()?.connections || {};
@@ -127,6 +128,8 @@ export class ConnectionManager {
127
128
 
128
129
  private handleConnClosed(conn: DataConnection): void {
129
130
  this.pool.delete(conn.peer);
131
+ // 同步移除 PeerJS 内部引用,避免僵尸连接堆积
132
+ this.deps.getPeer()?._removeConnection(conn);
130
133
  this.deps.onConnClosed(conn);
131
134
  }
132
135
 
@@ -7,7 +7,7 @@ import {
7
7
  PING_TIMEOUT,
8
8
  UNAUTHORIZED,
9
9
  } from './constant';
10
- import { DataConnection, Peer, PeerOptions } from 'peerjs';
10
+ import { DataConnection, Peer, PeerOptions, ServerMessageType } from 'peerjs';
11
11
  import {
12
12
  IDeviceStatus,
13
13
  IMessage,
@@ -89,11 +89,11 @@ export abstract class PeerTransfer {
89
89
  // ── Peer lifecycle ──────────────────────────────────────────────
90
90
 
91
91
  async createPeer(force?: boolean): Promise<Peer> {
92
- console.info('createPeer##', this.peer?.open, force);
93
92
  this._exited = false;
94
93
  if (this.peer?.open && !force) {
95
94
  return this.peer;
96
95
  }
96
+ console.info('create peer', Date.now());
97
97
  this.destroyPeer();
98
98
  await this.reloadConfig();
99
99
 
@@ -103,7 +103,13 @@ export abstract class PeerTransfer {
103
103
  await this.waitForOpen(peer);
104
104
  this.destroyed = false;
105
105
  peer.on('close', () => {
106
- setTimeout(() => this.destroyed && this.reconnect(), PEER_CLOSE_RECONNECT_TIMEOUT);
106
+ // 仅当 Peer 非主动销毁(stop/clearInstance/重建)时才重连
107
+ setTimeout(() => {
108
+ if (this.destroyed || this._exited) {
109
+ return;
110
+ }
111
+ this.reconnect();
112
+ }, PEER_CLOSE_RECONNECT_TIMEOUT);
107
113
  });
108
114
 
109
115
  peer.on('error', (err) => {
@@ -128,6 +134,10 @@ export abstract class PeerTransfer {
128
134
  socket?.on('message', (message: IMessage) => {
129
135
  this.handleSocketMessage(message);
130
136
  });
137
+ // signaling socket 断开时主动重连(兜底:部分场景不触发 peer error)
138
+ socket?.on('disconnected', () => {
139
+ this.reconnect();
140
+ });
131
141
 
132
142
  // 启动连接健康检查
133
143
  this.connectionManager.startHealthCheck();
@@ -190,6 +200,9 @@ export abstract class PeerTransfer {
190
200
  case 'HEARTBEAT':
191
201
  this.resetHeartbeatTimer();
192
202
  break;
203
+ case 'RELOAD':
204
+ this.reconnect(true);
205
+ break;
193
206
  case 'ERROR':
194
207
  if (message.payload?.msg === CONNECTION_PEER_CONFLICT) {
195
208
  this.getStore().dispatch({
@@ -198,6 +211,8 @@ export abstract class PeerTransfer {
198
211
  });
199
212
  }
200
213
  break;
214
+ default:
215
+ break;
201
216
  }
202
217
  }
203
218
 
@@ -309,13 +324,6 @@ export abstract class PeerTransfer {
309
324
  private onConnClosed(conn: DataConnection) {
310
325
  const reqIds = this.connRequests.get(conn.connectionId);
311
326
  if (reqIds) {
312
- // for (const reqId of reqIds) {
313
- // const cb = this.requests.get(reqId);
314
- // if (cb) {
315
- // cb({ error: { message: 'connection closed', code: 'CONN_CLOSED' } } as any);
316
- // this.requests.delete(reqId);
317
- // }
318
- // }
319
327
  this.connRequests.delete(conn.connectionId);
320
328
  }
321
329
  }
@@ -351,7 +359,6 @@ export abstract class PeerTransfer {
351
359
  if (this.destroyed) {
352
360
  return { ...payload, body: {}, error: { message: 'destroyed', code: 'CONN_CLOSED' } } as any;
353
361
  }
354
-
355
362
  const conn = await this.connectToPeer(peerId);
356
363
  if (!this.isValidConnection(conn)) {
357
364
  return {
@@ -554,6 +561,7 @@ export abstract class PeerTransfer {
554
561
  // ── Router integration ──────────────────────────────────────────
555
562
 
556
563
  async onRequest(conn: DataConnection, message: PeerMessage) {
564
+ console.info('onRequest===>', message.route);
557
565
  this.resetIdleTimer();
558
566
  try {
559
567
  await this.router.run(conn, message);
@@ -563,6 +571,7 @@ export abstract class PeerTransfer {
563
571
  }
564
572
 
565
573
  async onResponse(_conn: DataConnection, message: PeerMessage) {
574
+ console.info('onResponse<====', message.route);
566
575
  this.resetIdleTimer();
567
576
  // 优先检查 health check ping 回调
568
577
  const cb = this.requests.get(message.requestId);
@@ -618,7 +627,7 @@ export abstract class PeerTransfer {
618
627
  }
619
628
  this.heartbeatTimer = setTimeout(() => {
620
629
  if (!this.destroyed) {
621
- this.reconnect(true);
630
+ this.reconnect();
622
631
  }
623
632
  }, HEARTBEAT_TIMEOUT);
624
633
  }
@@ -668,4 +677,12 @@ export abstract class PeerTransfer {
668
677
  this.peer?.removeAllListeners();
669
678
  this.peer = undefined;
670
679
  }
680
+
681
+ askReload(peerId: string) {
682
+ this.peer?.socket.send({
683
+ type: 'RELOAD',
684
+ payload: {},
685
+ dst: peerId,
686
+ });
687
+ }
671
688
  }