@opensumi/ide-connection 3.0.2-next-1715690415.0 → 3.0.2-next-1715773842.0
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/browser/ws-channel-handler.d.ts +6 -0
- package/lib/browser/ws-channel-handler.d.ts.map +1 -1
- package/lib/browser/ws-channel-handler.js +50 -4
- package/lib/browser/ws-channel-handler.js.map +1 -1
- package/lib/common/fury-extends/one-of.d.ts +2 -1
- package/lib/common/fury-extends/one-of.d.ts.map +1 -1
- package/lib/common/fury-extends/one-of.js +12 -5
- package/lib/common/fury-extends/one-of.js.map +1 -1
- package/lib/common/server-handler.d.ts +2 -2
- package/lib/common/server-handler.d.ts.map +1 -1
- package/lib/common/server-handler.js +24 -11
- package/lib/common/server-handler.js.map +1 -1
- package/lib/common/ws-channel.d.ts +65 -24
- package/lib/common/ws-channel.d.ts.map +1 -1
- package/lib/common/ws-channel.js +51 -7
- package/lib/common/ws-channel.js.map +1 -1
- package/lib/node/ws.d.ts.map +1 -1
- package/lib/node/ws.js +1 -0
- package/lib/node/ws.js.map +1 -1
- package/package.json +5 -5
- package/src/browser/ws-channel-handler.ts +56 -7
- package/src/common/fury-extends/one-of.ts +12 -3
- package/src/common/server-handler.ts +39 -17
- package/src/common/ws-channel.ts +110 -39
- package/src/node/ws.ts +1 -0
package/src/common/ws-channel.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { Type } from '@furyjs/fury';
|
|
2
2
|
|
|
3
3
|
import { EventEmitter } from '@opensumi/events';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
DisposableCollection,
|
|
6
|
+
DisposableStore,
|
|
7
|
+
EventQueue,
|
|
8
|
+
StateTracer,
|
|
9
|
+
randomString,
|
|
10
|
+
} from '@opensumi/ide-core-common';
|
|
5
11
|
|
|
6
12
|
import { IConnectionShape } from './connection/types';
|
|
7
|
-
import {
|
|
13
|
+
import { oneOf } from './fury-extends/one-of';
|
|
8
14
|
import { ISumiConnectionOptions, SumiConnection } from './rpc/connection';
|
|
9
15
|
import { ILogger } from './types';
|
|
10
16
|
|
|
@@ -26,27 +32,6 @@ export interface PongMessage {
|
|
|
26
32
|
clientId: string;
|
|
27
33
|
}
|
|
28
34
|
|
|
29
|
-
/**
|
|
30
|
-
* `open` message is used to open a new channel.
|
|
31
|
-
* `path` is used to identify which handler should be used to handle the channel.
|
|
32
|
-
* `clientId` is used to identify the client.
|
|
33
|
-
*/
|
|
34
|
-
export interface OpenMessage {
|
|
35
|
-
kind: 'open';
|
|
36
|
-
id: string;
|
|
37
|
-
path: string;
|
|
38
|
-
clientId: string;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* when server receive a `open` message, it should reply a `server-ready` message.
|
|
43
|
-
* this is indicate that the channel is ready to use.
|
|
44
|
-
*/
|
|
45
|
-
export interface ServerReadyMessage {
|
|
46
|
-
kind: 'server-ready';
|
|
47
|
-
id: string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
35
|
/**
|
|
51
36
|
* `data` message indicate that the channel has received some data.
|
|
52
37
|
* the `content` field is the data, it should be a string.
|
|
@@ -70,15 +55,6 @@ export interface CloseMessage {
|
|
|
70
55
|
reason: string;
|
|
71
56
|
}
|
|
72
57
|
|
|
73
|
-
export type ChannelMessage =
|
|
74
|
-
| PingMessage
|
|
75
|
-
| PongMessage
|
|
76
|
-
| OpenMessage
|
|
77
|
-
| ServerReadyMessage
|
|
78
|
-
| DataMessage
|
|
79
|
-
| BinaryMessage
|
|
80
|
-
| CloseMessage;
|
|
81
|
-
|
|
82
58
|
export interface IWSChannelCreateOptions {
|
|
83
59
|
/**
|
|
84
60
|
* every channel's unique id, it only used in client to server architecture.
|
|
@@ -172,6 +148,14 @@ export class WSChannel {
|
|
|
172
148
|
this._isServerReady = false;
|
|
173
149
|
}
|
|
174
150
|
|
|
151
|
+
onServerReady(cb: () => void) {
|
|
152
|
+
if (this._isServerReady) {
|
|
153
|
+
cb();
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
return this.emitter.on('open', cb);
|
|
157
|
+
}
|
|
158
|
+
|
|
175
159
|
resume() {
|
|
176
160
|
this._isServerReady = true;
|
|
177
161
|
if (this.sendQueue) {
|
|
@@ -185,6 +169,7 @@ export class WSChannel {
|
|
|
185
169
|
dispatch(msg: ChannelMessage) {
|
|
186
170
|
switch (msg.kind) {
|
|
187
171
|
case 'server-ready':
|
|
172
|
+
this.stateTracer.fulfill(msg.token);
|
|
188
173
|
this.resume();
|
|
189
174
|
if (this.timer) {
|
|
190
175
|
clearTimeout(this.timer);
|
|
@@ -200,27 +185,45 @@ export class WSChannel {
|
|
|
200
185
|
}
|
|
201
186
|
}
|
|
202
187
|
|
|
203
|
-
|
|
188
|
+
stateTracer = this._disposables.add(new StateTracer());
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* @param connectionToken 一个 connection token 用于在全链路中追踪一个 channel 的生命周期,防止 channel 被重复打开
|
|
192
|
+
*/
|
|
193
|
+
open(path: string, clientId: string, connectionToken = randomString(16)) {
|
|
204
194
|
this.channelPath = path;
|
|
195
|
+
|
|
196
|
+
if (this.stateTracer.has(connectionToken)) {
|
|
197
|
+
this.logger.warn(
|
|
198
|
+
`channel already opened or in progress, path: ${path}, clientId: ${clientId}, connectionToken: ${connectionToken}`,
|
|
199
|
+
);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
this.stateTracer.record(connectionToken);
|
|
204
|
+
|
|
205
205
|
this.connection.send(
|
|
206
206
|
stringify({
|
|
207
207
|
kind: 'open',
|
|
208
208
|
id: this.id,
|
|
209
209
|
path,
|
|
210
210
|
clientId,
|
|
211
|
+
connectionToken,
|
|
211
212
|
}),
|
|
212
213
|
);
|
|
213
214
|
|
|
214
215
|
if (this._ensureServerReady) {
|
|
215
|
-
this.ensureOpenSend(path, clientId);
|
|
216
|
+
this.ensureOpenSend(path, clientId, connectionToken);
|
|
216
217
|
}
|
|
218
|
+
|
|
219
|
+
return connectionToken;
|
|
217
220
|
}
|
|
218
221
|
|
|
219
222
|
protected timer: NodeJS.Timeout;
|
|
220
223
|
/**
|
|
221
224
|
* 启动定时器,确保 server-ready 消息在一定时间内到达
|
|
222
225
|
*/
|
|
223
|
-
protected ensureOpenSend(path: string, clientId: string) {
|
|
226
|
+
protected ensureOpenSend(path: string, clientId: string, connectionToken: string) {
|
|
224
227
|
if (this.timer) {
|
|
225
228
|
clearTimeout(this.timer);
|
|
226
229
|
}
|
|
@@ -228,8 +231,8 @@ export class WSChannel {
|
|
|
228
231
|
if (this._isServerReady) {
|
|
229
232
|
return;
|
|
230
233
|
}
|
|
231
|
-
|
|
232
|
-
this.open(path, clientId);
|
|
234
|
+
this.stateTracer.delete(connectionToken);
|
|
235
|
+
this.open(path, clientId, connectionToken);
|
|
233
236
|
}, 500);
|
|
234
237
|
}
|
|
235
238
|
|
|
@@ -300,20 +303,45 @@ interface IWSServerChannelCreateOptions extends IWSChannelCreateOptions {
|
|
|
300
303
|
* The server side channel, it will send a `server-ready` message after it receive a `open` message.
|
|
301
304
|
*/
|
|
302
305
|
export class WSServerChannel extends WSChannel {
|
|
306
|
+
messageQueue: ChannelMessage[] = [];
|
|
307
|
+
|
|
303
308
|
clientId: string;
|
|
304
309
|
constructor(public connection: IConnectionShape<Uint8Array>, options: IWSServerChannelCreateOptions) {
|
|
305
310
|
super(connection, options);
|
|
306
311
|
this.clientId = options.clientId;
|
|
307
312
|
}
|
|
308
|
-
serverReady() {
|
|
313
|
+
serverReady(token: string) {
|
|
309
314
|
this.connection.send(
|
|
310
315
|
stringify({
|
|
311
316
|
kind: 'server-ready',
|
|
312
317
|
id: this.id,
|
|
318
|
+
token,
|
|
313
319
|
}),
|
|
314
320
|
);
|
|
315
321
|
}
|
|
322
|
+
|
|
323
|
+
dispatch(msg: ChannelMessage) {
|
|
324
|
+
switch (msg.kind) {
|
|
325
|
+
case 'data':
|
|
326
|
+
this.emitter.emit('message', msg.content);
|
|
327
|
+
break;
|
|
328
|
+
case 'binary':
|
|
329
|
+
this.emitter.emit('binary', msg.binary);
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
316
333
|
}
|
|
334
|
+
|
|
335
|
+
export type ChannelMessage =
|
|
336
|
+
| PingMessage
|
|
337
|
+
| PongMessage
|
|
338
|
+
| OpenMessage
|
|
339
|
+
| ServerReadyMessage
|
|
340
|
+
| DataMessage
|
|
341
|
+
| BinaryMessage
|
|
342
|
+
| CloseMessage
|
|
343
|
+
| ErrorMessage;
|
|
344
|
+
|
|
317
345
|
export const PingProtocol = Type.object('ping', {
|
|
318
346
|
clientId: Type.string(),
|
|
319
347
|
id: Type.string(),
|
|
@@ -324,14 +352,56 @@ export const PongProtocol = Type.object('pong', {
|
|
|
324
352
|
id: Type.string(),
|
|
325
353
|
});
|
|
326
354
|
|
|
355
|
+
/**
|
|
356
|
+
* `open` message is used to open a new channel.
|
|
357
|
+
* `path` is used to identify which handler should be used to handle the channel.
|
|
358
|
+
* `clientId` is used to identify the client.
|
|
359
|
+
*/
|
|
360
|
+
export interface OpenMessage {
|
|
361
|
+
kind: 'open';
|
|
362
|
+
id: string;
|
|
363
|
+
path: string;
|
|
364
|
+
clientId: string;
|
|
365
|
+
connectionToken: string;
|
|
366
|
+
}
|
|
367
|
+
|
|
327
368
|
export const OpenProtocol = Type.object('open', {
|
|
328
369
|
clientId: Type.string(),
|
|
329
370
|
id: Type.string(),
|
|
330
371
|
path: Type.string(),
|
|
372
|
+
connectionToken: Type.string(),
|
|
331
373
|
});
|
|
332
374
|
|
|
375
|
+
/**
|
|
376
|
+
* when server receive a `open` message, it should reply a `server-ready` message.
|
|
377
|
+
* this is indicate that the channel is ready to use.
|
|
378
|
+
*/
|
|
379
|
+
export interface ServerReadyMessage {
|
|
380
|
+
kind: 'server-ready';
|
|
381
|
+
id: string;
|
|
382
|
+
token: string;
|
|
383
|
+
}
|
|
384
|
+
|
|
333
385
|
export const ServerReadyProtocol = Type.object('server-ready', {
|
|
334
386
|
id: Type.string(),
|
|
387
|
+
token: Type.string(),
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
export enum ErrorMessageCode {
|
|
391
|
+
ChannelNotFound = 1,
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export interface ErrorMessage {
|
|
395
|
+
kind: 'error';
|
|
396
|
+
id: string;
|
|
397
|
+
code: ErrorMessageCode;
|
|
398
|
+
message: string;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
export const ErrorProtocol = Type.object('error', {
|
|
402
|
+
id: Type.string(),
|
|
403
|
+
code: Type.uint16(),
|
|
404
|
+
message: Type.string(),
|
|
335
405
|
});
|
|
336
406
|
|
|
337
407
|
export const DataProtocol = Type.object('data', {
|
|
@@ -350,7 +420,7 @@ export const CloseProtocol = Type.object('close', {
|
|
|
350
420
|
reason: Type.string(),
|
|
351
421
|
});
|
|
352
422
|
|
|
353
|
-
const serializer =
|
|
423
|
+
const serializer = oneOf([
|
|
354
424
|
PingProtocol,
|
|
355
425
|
PongProtocol,
|
|
356
426
|
OpenProtocol,
|
|
@@ -358,6 +428,7 @@ const serializer = oneOf7([
|
|
|
358
428
|
DataProtocol,
|
|
359
429
|
BinaryProtocol,
|
|
360
430
|
CloseProtocol,
|
|
431
|
+
ErrorProtocol,
|
|
361
432
|
]);
|
|
362
433
|
|
|
363
434
|
export function stringify(obj: ChannelMessage): Uint8Array {
|