@opensumi/ide-connection 3.1.2-next-1718957810.0 → 3.1.2
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/common/channel/types.d.ts +16 -15
- package/lib/common/channel/types.d.ts.map +1 -1
- package/lib/common/rpc/message-io.d.ts +5 -0
- package/lib/common/rpc/message-io.d.ts.map +1 -1
- package/lib/common/rpc/message-io.js +5 -0
- package/lib/common/rpc/message-io.js.map +1 -1
- package/lib/common/rpc-service/center.d.ts.map +1 -1
- package/lib/common/rpc-service/center.js +0 -2
- package/lib/common/rpc-service/center.js.map +1 -1
- package/lib/common/serializer/fury.d.ts +16 -16
- package/lib/common/serializer/fury.d.ts.map +1 -1
- package/lib/common/serializer/fury.js +34 -13
- package/lib/common/serializer/fury.js.map +1 -1
- package/lib/common/server-handler.d.ts.map +1 -1
- package/lib/common/server-handler.js +12 -15
- package/lib/common/server-handler.js.map +1 -1
- package/lib/common/ws-channel.d.ts +12 -32
- package/lib/common/ws-channel.d.ts.map +1 -1
- package/lib/common/ws-channel.js +38 -93
- package/lib/common/ws-channel.js.map +1 -1
- package/package.json +5 -5
- package/src/common/channel/types.ts +16 -16
- package/src/common/rpc/message-io.ts +5 -0
- package/src/common/rpc-service/center.ts +0 -2
- package/src/common/serializer/fury.ts +10 -16
- package/src/common/server-handler.ts +13 -17
- package/src/common/ws-channel.ts +48 -119
package/src/common/ws-channel.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventEmitter } from '@opensumi/events';
|
|
2
|
-
import { DisposableStore, EventQueue, randomString } from '@opensumi/ide-core-common';
|
|
2
|
+
import { DisposableStore, EventQueue, StateTracer, randomString } from '@opensumi/ide-core-common';
|
|
3
3
|
|
|
4
4
|
import { ChannelMessage, ErrorMessageCode } from './channel/types';
|
|
5
5
|
import { IConnectionShape } from './connection/types';
|
|
@@ -15,82 +15,6 @@ export interface IWSChannelCreateOptions {
|
|
|
15
15
|
logger?: ILogger;
|
|
16
16
|
|
|
17
17
|
ensureServerReady?: boolean;
|
|
18
|
-
deliveryTimeout?: number;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
enum MessageDeliveryState {
|
|
22
|
-
ReSend,
|
|
23
|
-
Sended,
|
|
24
|
-
Success,
|
|
25
|
-
Failed,
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
class StateTracer {
|
|
29
|
-
private map = new Map<string, MessageDeliveryState>();
|
|
30
|
-
|
|
31
|
-
protected deliveryTimeout = 500;
|
|
32
|
-
protected timerMap = new Map<string, NodeJS.Timeout>();
|
|
33
|
-
|
|
34
|
-
setDeliveryTimeout(timeout: number) {
|
|
35
|
-
this.deliveryTimeout = timeout;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
protected set(traceId: string, state: MessageDeliveryState) {
|
|
39
|
-
this.map.set(traceId, state);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
get(traceId: string) {
|
|
43
|
-
return this.map.get(traceId);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
success(traceId: string) {
|
|
47
|
-
this.map.set(traceId, MessageDeliveryState.Success);
|
|
48
|
-
const timer = this.timerMap.get(traceId);
|
|
49
|
-
if (timer) {
|
|
50
|
-
clearTimeout(timer);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
dispose() {
|
|
55
|
-
this.timerMap.forEach((timer) => {
|
|
56
|
-
clearTimeout(timer);
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
stop(traceId: string) {
|
|
61
|
-
const timer = this.timerMap.get(traceId);
|
|
62
|
-
if (timer) {
|
|
63
|
-
clearTimeout(timer);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
send(
|
|
68
|
-
traceId: string,
|
|
69
|
-
options: {
|
|
70
|
-
whenRetry: () => void;
|
|
71
|
-
},
|
|
72
|
-
) {
|
|
73
|
-
this.set(traceId, MessageDeliveryState.Sended);
|
|
74
|
-
this.guard(traceId, options);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
guard(
|
|
78
|
-
traceId: string,
|
|
79
|
-
options: {
|
|
80
|
-
whenRetry: () => void;
|
|
81
|
-
},
|
|
82
|
-
) {
|
|
83
|
-
const timer = this.timerMap.get(traceId);
|
|
84
|
-
if (timer) {
|
|
85
|
-
clearTimeout(timer);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const newTimer = setTimeout(() => {
|
|
89
|
-
this.set(traceId, MessageDeliveryState.ReSend);
|
|
90
|
-
options.whenRetry();
|
|
91
|
-
}, this.deliveryTimeout);
|
|
92
|
-
this.timerMap.set(traceId, newTimer);
|
|
93
|
-
}
|
|
94
18
|
}
|
|
95
19
|
|
|
96
20
|
export class WSChannel {
|
|
@@ -111,8 +35,6 @@ export class WSChannel {
|
|
|
111
35
|
protected _isServerReady = false;
|
|
112
36
|
protected _ensureServerReady: boolean | undefined;
|
|
113
37
|
|
|
114
|
-
protected stateTracer = new StateTracer();
|
|
115
|
-
|
|
116
38
|
public id: string;
|
|
117
39
|
|
|
118
40
|
public channelPath: string;
|
|
@@ -131,9 +53,6 @@ export class WSChannel {
|
|
|
131
53
|
}
|
|
132
54
|
|
|
133
55
|
this._ensureServerReady = Boolean(ensureServerReady);
|
|
134
|
-
if (options.deliveryTimeout) {
|
|
135
|
-
this.stateTracer.setDeliveryTimeout(options.deliveryTimeout);
|
|
136
|
-
}
|
|
137
56
|
|
|
138
57
|
this._disposables.add(this.emitter.on('binary', (data) => this.onBinaryQueue.push(data)));
|
|
139
58
|
}
|
|
@@ -149,30 +68,6 @@ export class WSChannel {
|
|
|
149
68
|
this.connection.send(data);
|
|
150
69
|
}
|
|
151
70
|
|
|
152
|
-
/**
|
|
153
|
-
* @param traceId 一个 connection token 用于在全链路中追踪一个消息的生命周期,防止消息未发送或者重复发送
|
|
154
|
-
*/
|
|
155
|
-
protected ensureMessageDeliveried(data: ChannelMessage, traceId = randomString(16)) {
|
|
156
|
-
const state = this.stateTracer.get(traceId);
|
|
157
|
-
if (state && state >= MessageDeliveryState.Sended) {
|
|
158
|
-
this.logger.error(`message already send already success or in progress, traceId: ${traceId}, state: ${state}`);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
data.traceId = traceId;
|
|
163
|
-
this.connection.send(data);
|
|
164
|
-
|
|
165
|
-
this.stateTracer.send(traceId, {
|
|
166
|
-
whenRetry: () => {
|
|
167
|
-
if (this._isServerReady) {
|
|
168
|
-
this.stateTracer.stop(traceId);
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
this.ensureMessageDeliveried(data, traceId);
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
|
|
176
71
|
onMessage(cb: (data: string) => any) {
|
|
177
72
|
return this.emitter.on('message', cb);
|
|
178
73
|
}
|
|
@@ -211,11 +106,11 @@ export class WSChannel {
|
|
|
211
106
|
dispatch(msg: ChannelMessage) {
|
|
212
107
|
switch (msg.kind) {
|
|
213
108
|
case 'server-ready':
|
|
214
|
-
|
|
215
|
-
this.stateTracer.success(msg.traceId);
|
|
216
|
-
}
|
|
217
|
-
|
|
109
|
+
this.stateTracer.fulfill(msg.token);
|
|
218
110
|
this.resume();
|
|
111
|
+
if (this.timer) {
|
|
112
|
+
clearTimeout(this.timer);
|
|
113
|
+
}
|
|
219
114
|
this.emitter.emit('open', msg.id);
|
|
220
115
|
break;
|
|
221
116
|
case 'data':
|
|
@@ -241,24 +136,56 @@ export class WSChannel {
|
|
|
241
136
|
}
|
|
242
137
|
}
|
|
243
138
|
|
|
244
|
-
|
|
139
|
+
stateTracer = this._disposables.add(new StateTracer());
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @param connectionToken 一个 connection token 用于在全链路中追踪一个 channel 的生命周期,防止 channel 被重复打开
|
|
143
|
+
*/
|
|
144
|
+
open(path: string, clientId: string, connectionToken = randomString(16)) {
|
|
245
145
|
this.channelPath = path;
|
|
246
146
|
this.clientId = clientId;
|
|
247
147
|
|
|
248
148
|
this.LOG_TAG = `[WSChannel id=${this.id} path=${path}]`;
|
|
249
149
|
|
|
250
|
-
|
|
150
|
+
if (this.stateTracer.has(connectionToken)) {
|
|
151
|
+
this.logger.warn(
|
|
152
|
+
`channel already opened or in progress, path: ${path}, clientId: ${clientId}, connectionToken: ${connectionToken}`,
|
|
153
|
+
);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
this.stateTracer.record(connectionToken);
|
|
158
|
+
|
|
159
|
+
this.connection.send({
|
|
251
160
|
kind: 'open',
|
|
252
161
|
id: this.id,
|
|
253
162
|
path,
|
|
254
163
|
clientId,
|
|
255
|
-
|
|
164
|
+
connectionToken,
|
|
165
|
+
});
|
|
256
166
|
|
|
257
167
|
if (this._ensureServerReady) {
|
|
258
|
-
this.
|
|
259
|
-
} else {
|
|
260
|
-
this.connection.send(msg);
|
|
168
|
+
this.ensureOpenSend(path, clientId, connectionToken);
|
|
261
169
|
}
|
|
170
|
+
|
|
171
|
+
return connectionToken;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
protected timer: NodeJS.Timeout;
|
|
175
|
+
/**
|
|
176
|
+
* 启动定时器,确保 server-ready 消息在一定时间内到达
|
|
177
|
+
*/
|
|
178
|
+
protected ensureOpenSend(path: string, clientId: string, connectionToken: string) {
|
|
179
|
+
if (this.timer) {
|
|
180
|
+
clearTimeout(this.timer);
|
|
181
|
+
}
|
|
182
|
+
this.timer = setTimeout(() => {
|
|
183
|
+
if (this._isServerReady) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
this.stateTracer.delete(connectionToken);
|
|
187
|
+
this.open(path, clientId, connectionToken);
|
|
188
|
+
}, 500);
|
|
262
189
|
}
|
|
263
190
|
|
|
264
191
|
send(content: string) {
|
|
@@ -308,7 +235,9 @@ export class WSChannel {
|
|
|
308
235
|
}
|
|
309
236
|
|
|
310
237
|
dispose() {
|
|
311
|
-
this.
|
|
238
|
+
if (this.timer) {
|
|
239
|
+
clearTimeout(this.timer);
|
|
240
|
+
}
|
|
312
241
|
this.sendQueue = [];
|
|
313
242
|
this._disposables.dispose();
|
|
314
243
|
}
|
|
@@ -337,11 +266,11 @@ export class WSServerChannel extends WSChannel {
|
|
|
337
266
|
this.clientId = options.clientId;
|
|
338
267
|
}
|
|
339
268
|
|
|
340
|
-
serverReady(
|
|
269
|
+
serverReady(token: string) {
|
|
341
270
|
this.connection.send({
|
|
342
271
|
kind: 'server-ready',
|
|
343
272
|
id: this.id,
|
|
344
|
-
|
|
273
|
+
token,
|
|
345
274
|
});
|
|
346
275
|
}
|
|
347
276
|
|