@opensumi/ide-connection 3.0.2-next-1715826860.0 → 3.0.2-next-1715852509.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.
Files changed (34) hide show
  1. package/lib/browser/ws-channel-handler.d.ts +0 -6
  2. package/lib/browser/ws-channel-handler.d.ts.map +1 -1
  3. package/lib/browser/ws-channel-handler.js +9 -68
  4. package/lib/browser/ws-channel-handler.js.map +1 -1
  5. package/lib/common/connection/drivers/reconnecting-websocket.d.ts +1 -1
  6. package/lib/common/connection/drivers/reconnecting-websocket.d.ts.map +1 -1
  7. package/lib/common/connection/drivers/reconnecting-websocket.js +1 -1
  8. package/lib/common/connection/drivers/reconnecting-websocket.js.map +1 -1
  9. package/lib/common/fury-extends/one-of.d.ts +1 -2
  10. package/lib/common/fury-extends/one-of.d.ts.map +1 -1
  11. package/lib/common/fury-extends/one-of.js +5 -12
  12. package/lib/common/fury-extends/one-of.js.map +1 -1
  13. package/lib/common/rpc/connection.d.ts.map +1 -1
  14. package/lib/common/rpc/connection.js +6 -3
  15. package/lib/common/rpc/connection.js.map +1 -1
  16. package/lib/common/server-handler.d.ts +4 -4
  17. package/lib/common/server-handler.d.ts.map +1 -1
  18. package/lib/common/server-handler.js +12 -25
  19. package/lib/common/server-handler.js.map +1 -1
  20. package/lib/common/ws-channel.d.ts +23 -77
  21. package/lib/common/ws-channel.d.ts.map +1 -1
  22. package/lib/common/ws-channel.js +4 -77
  23. package/lib/common/ws-channel.js.map +1 -1
  24. package/lib/node/ws.d.ts.map +1 -1
  25. package/lib/node/ws.js +0 -1
  26. package/lib/node/ws.js.map +1 -1
  27. package/package.json +6 -6
  28. package/src/browser/ws-channel-handler.ts +10 -74
  29. package/src/common/connection/drivers/reconnecting-websocket.ts +3 -5
  30. package/src/common/fury-extends/one-of.ts +3 -12
  31. package/src/common/rpc/connection.ts +149 -148
  32. package/src/common/server-handler.ts +18 -41
  33. package/src/common/ws-channel.ts +35 -143
  34. package/src/node/ws.ts +0 -1
@@ -195,185 +195,186 @@ export class SumiConnection implements IDisposable {
195
195
  listen() {
196
196
  const { reader } = this.io;
197
197
 
198
- this.disposable.add(
199
- this.socket.onMessage((data) => {
200
- reader.reset(data);
201
- // skip version, currently only have version 1
202
- reader.skip(1);
203
-
204
- const opType = reader.uint8() as OperationType;
205
- const requestId = reader.uint32();
206
-
207
- if (this._timeoutHandles.has(requestId)) {
208
- // Ignore some jest test scenarios where clearTimeout is not defined.
209
- if (typeof clearTimeout === 'function') {
210
- // @ts-ignore
211
- clearTimeout(this._timeoutHandles.get(requestId));
212
- }
213
- this._timeoutHandles.delete(requestId);
198
+ const toDispose = this.socket.onMessage((data) => {
199
+ reader.reset(data);
200
+ // skip version, currently only have version 1
201
+ reader.skip(1);
202
+
203
+ const opType = reader.uint8() as OperationType;
204
+ const requestId = reader.uint32();
205
+
206
+ if (this._timeoutHandles.has(requestId)) {
207
+ // Ignore some jest test scenarios where clearTimeout is not defined.
208
+ if (typeof clearTimeout === 'function') {
209
+ // @ts-ignore
210
+ clearTimeout(this._timeoutHandles.get(requestId));
214
211
  }
212
+ this._timeoutHandles.delete(requestId);
213
+ }
215
214
 
216
- switch (opType) {
217
- case OperationType.Response: {
218
- const method = reader.stringOfVarUInt32();
219
- const status = reader.uint16();
215
+ switch (opType) {
216
+ case OperationType.Response: {
217
+ const method = reader.stringOfVarUInt32();
218
+ const status = reader.uint16();
220
219
 
221
- const runCallback = (headers: IResponseHeaders, error?: any, result?: any) => {
222
- const callback = this._callbacks.get(requestId);
223
- if (!callback) {
224
- this.logger.error(`Cannot find callback for request ${requestId}: ${method}, status: ${status}`);
225
- return;
226
- }
220
+ const runCallback = (headers: IResponseHeaders, error?: any, result?: any) => {
221
+ const callback = this._callbacks.get(requestId);
222
+ if (!callback) {
223
+ this.logger.error(`Cannot find callback for request ${requestId}`);
224
+ return;
225
+ }
226
+
227
+ this._callbacks.delete(requestId);
227
228
 
228
- this._callbacks.delete(requestId);
229
+ callback(headers, error, result);
230
+ };
229
231
 
230
- callback(headers, error, result);
231
- };
232
+ const headers = this.io.responseHeadersSerializer.read();
233
+ let err: any;
234
+ let result: any;
235
+ if (status === Status.Err) {
236
+ // todo: move to processor
237
+ const content = reader.stringOfVarUInt32();
238
+ err = parseError(content);
239
+ } else {
240
+ result = this.io.getProcessor(method).readResponse();
241
+ }
232
242
 
233
- const headers = this.io.responseHeadersSerializer.read();
234
- let err: any;
235
- let result: any;
236
- if (status === Status.Err) {
237
- // todo: move to processor
238
- const content = reader.stringOfVarUInt32();
239
- err = parseError(content);
243
+ if (headers && headers.chunked) {
244
+ let activeReq: SumiReadableStream<any>;
245
+ if (this.activeRequestPool.has(requestId)) {
246
+ activeReq = this.activeRequestPool.get(requestId)!;
240
247
  } else {
241
- result = this.io.getProcessor(method).readResponse();
248
+ // new stream request
249
+ activeReq = new SumiReadableStream();
250
+ this.activeRequestPool.set(requestId, activeReq);
251
+ // resolve `activeReq` to caller
252
+ runCallback(headers, undefined, activeReq);
242
253
  }
243
254
 
244
- if (headers && headers.chunked) {
245
- let activeReq: SumiReadableStream<any>;
246
- if (this.activeRequestPool.has(requestId)) {
247
- activeReq = this.activeRequestPool.get(requestId)!;
248
- } else {
249
- // new stream request
250
- activeReq = new SumiReadableStream();
251
- this.activeRequestPool.set(requestId, activeReq);
252
- // resolve `activeReq` to caller
253
- runCallback(headers, undefined, activeReq);
254
- }
255
-
256
- if (result === null) {
257
- // when result is null, it means the stream is ended.
258
- activeReq.end();
259
- this.activeRequestPool.delete(requestId);
260
- break;
261
- }
262
-
263
- if (err) {
264
- activeReq.emitError(err);
265
- break;
266
- }
255
+ if (result === null) {
256
+ // when result is null, it means the stream is ended.
257
+ activeReq.end();
258
+ this.activeRequestPool.delete(requestId);
259
+ break;
260
+ }
267
261
 
268
- activeReq.emitData(result);
262
+ if (err) {
263
+ activeReq.emitError(err);
269
264
  break;
270
265
  }
271
266
 
272
- runCallback(headers, err, result);
267
+ activeReq.emitData(result);
273
268
  break;
274
269
  }
275
- case OperationType.Notification:
276
- // fall through
277
- case OperationType.Request: {
278
- const method = reader.stringOfVarUInt32();
279
- const headers = this.io.requestHeadersSerializer.read() as IRequestHeaders;
280
- const args = this.io.getProcessor(method).readRequest();
281
-
282
- if (headers.cancelable) {
283
- const tokenSource = new CancellationTokenSource();
284
- this._cancellationTokenSources.set(requestId, tokenSource);
285
- args.push(tokenSource.token);
286
-
287
- if (this._knownCanceledRequests.has(requestId)) {
288
- tokenSource.cancel();
289
- this._knownCanceledRequests.delete(requestId);
290
- }
291
- }
292
270
 
293
- switch (opType) {
294
- case OperationType.Request: {
295
- this.capturer.captureOnRequest(requestId, method, args);
271
+ runCallback(headers, err, result);
272
+ break;
273
+ }
274
+ case OperationType.Notification:
275
+ // fall through
276
+ case OperationType.Request: {
277
+ const method = reader.stringOfVarUInt32();
278
+ const headers = this.io.requestHeadersSerializer.read() as IRequestHeaders;
279
+ const args = this.io.getProcessor(method).readRequest();
280
+
281
+ if (headers.cancelable) {
282
+ const tokenSource = new CancellationTokenSource();
283
+ this._cancellationTokenSources.set(requestId, tokenSource);
284
+ args.push(tokenSource.token);
285
+
286
+ if (this._knownCanceledRequests.has(requestId)) {
287
+ tokenSource.cancel();
288
+ this._knownCanceledRequests.delete(requestId);
289
+ }
290
+ }
296
291
 
297
- let promise: Promise<any>;
292
+ switch (opType) {
293
+ case OperationType.Request: {
294
+ this.capturer.captureOnRequest(requestId, method, args);
298
295
 
299
- try {
300
- let result: any;
296
+ let promise: Promise<any>;
301
297
 
302
- const handler = this._requestHandlers.get(method);
303
- if (handler) {
304
- result = handler(...args);
305
- } else if (this._starRequestHandler) {
306
- result = this._starRequestHandler(method, args);
307
- }
298
+ try {
299
+ let result: any;
308
300
 
309
- promise = Promise.resolve(result);
310
- } catch (err) {
311
- promise = Promise.reject(err);
301
+ const handler = this._requestHandlers.get(method);
302
+ if (handler) {
303
+ result = handler(...args);
304
+ } else if (this._starRequestHandler) {
305
+ result = this._starRequestHandler(method, args);
312
306
  }
313
307
 
314
- const onSuccess = (result: any) => {
315
- this.capturer.captureOnRequestResult(requestId, method, result);
316
-
317
- if (isReadableStream(result)) {
318
- listenReadable(result, {
319
- onData: (data) => {
320
- this.socket.send(this.io.Response(requestId, method, chunkedResponseHeaders, data));
321
- },
322
- onEnd: () => {
323
- this.socket.send(this.io.Response(requestId, method, chunkedResponseHeaders, null));
324
- },
325
- onError: (err) => {
326
- this.socket.send(this.io.Error(requestId, method, chunkedResponseHeaders, err));
327
- },
328
- });
329
- } else {
330
- this.socket.send(this.io.Response(requestId, method, nullHeaders, result));
331
- }
332
-
333
- this._cancellationTokenSources.delete(requestId);
334
- };
335
-
336
- const onError = (err: Error) => {
337
- this.traceRequestError(requestId, method, args, err);
338
-
339
- this.socket.send(this.io.Error(requestId, method, nullHeaders, err));
340
- this._cancellationTokenSources.delete(requestId);
341
- };
342
-
343
- promise.then(onSuccess).catch(onError);
344
- break;
308
+ promise = Promise.resolve(result);
309
+ } catch (err) {
310
+ promise = Promise.reject(err);
345
311
  }
346
- case OperationType.Notification: {
347
- this.capturer.captureOnNotification(requestId, method, args);
348
312
 
349
- const handler = this._notificationHandlers.get(method);
350
-
351
- if (handler) {
352
- handler(...args);
353
- } else if (this._starNotificationHandler) {
354
- this._starNotificationHandler(method, args);
313
+ const onSuccess = (result: any) => {
314
+ this.capturer.captureOnRequestResult(requestId, method, result);
315
+
316
+ if (isReadableStream(result)) {
317
+ listenReadable(result, {
318
+ onData: (data) => {
319
+ this.socket.send(this.io.Response(requestId, method, chunkedResponseHeaders, data));
320
+ },
321
+ onEnd: () => {
322
+ this.socket.send(this.io.Response(requestId, method, chunkedResponseHeaders, null));
323
+ },
324
+ onError: (err) => {
325
+ this.socket.send(this.io.Error(requestId, method, chunkedResponseHeaders, err));
326
+ },
327
+ });
328
+ } else {
329
+ this.socket.send(this.io.Response(requestId, method, nullHeaders, result));
355
330
  }
356
- break;
357
- }
331
+
332
+ this._cancellationTokenSources.delete(requestId);
333
+ };
334
+
335
+ const onError = (err: Error) => {
336
+ this.traceRequestError(requestId, method, args, err);
337
+
338
+ this.socket.send(this.io.Error(requestId, method, nullHeaders, err));
339
+ this._cancellationTokenSources.delete(requestId);
340
+ };
341
+
342
+ promise.then(onSuccess).catch(onError);
343
+ break;
358
344
  }
345
+ case OperationType.Notification: {
346
+ this.capturer.captureOnNotification(requestId, method, args);
359
347
 
360
- break;
361
- }
362
- case OperationType.Cancel: {
363
- const cancellationTokenSource = this._cancellationTokenSources.get(requestId);
364
- if (cancellationTokenSource) {
365
- cancellationTokenSource.cancel();
366
- } else {
367
- this._knownCanceledRequests.add(requestId);
348
+ const handler = this._notificationHandlers.get(method);
349
+
350
+ if (handler) {
351
+ handler(...args);
352
+ } else if (this._starNotificationHandler) {
353
+ this._starNotificationHandler(method, args);
354
+ }
355
+ break;
368
356
  }
369
- break;
370
357
  }
371
- default: {
372
- break;
358
+
359
+ break;
360
+ }
361
+ case OperationType.Cancel: {
362
+ const cancellationTokenSource = this._cancellationTokenSources.get(requestId);
363
+ if (cancellationTokenSource) {
364
+ cancellationTokenSource.cancel();
365
+ } else {
366
+ this._knownCanceledRequests.add(requestId);
373
367
  }
368
+ break;
369
+ }
370
+ default: {
371
+ break;
374
372
  }
375
- }),
376
- );
373
+ }
374
+ });
375
+ if (toDispose) {
376
+ this.disposable.add(toDispose);
377
+ }
377
378
  }
378
379
 
379
380
  dispose(): void {
@@ -1,14 +1,6 @@
1
1
  import { IConnectionShape } from './connection/types';
2
2
  import { ILogger } from './types';
3
- import {
4
- ChannelMessage,
5
- ErrorMessageCode,
6
- WSChannel,
7
- WSServerChannel,
8
- parse,
9
- pongMessage,
10
- stringify,
11
- } from './ws-channel';
3
+ import { ChannelMessage, WSChannel, WSServerChannel, parse, pongMessage } from './ws-channel';
12
4
 
13
5
  export interface IPathHandler {
14
6
  dispose: (channel: WSChannel, connectionId: string) => void;
@@ -76,7 +68,7 @@ export class CommonChannelPathHandler {
76
68
  });
77
69
  });
78
70
  }
79
- openChannel(path: string, channel: WSChannel, clientId: string) {
71
+ dispatchChannelOpen(path: string, channel: WSChannel, clientId: string) {
80
72
  // 根据 path 拿到注册的 handler
81
73
  let handlerArr = this.get(path);
82
74
  let params: Record<string, string> | undefined;
@@ -106,38 +98,31 @@ export class CommonChannelPathHandler {
106
98
  export const commonChannelPathHandler = new CommonChannelPathHandler();
107
99
 
108
100
  export abstract class BaseCommonChannelHandler {
109
- protected channelMap: Map<string, WSServerChannel> = new Map();
101
+ protected channelMap: Map<string, WSChannel> = new Map();
110
102
 
111
- protected heartbeatTimer: NodeJS.Timeout | null = null;
103
+ heartbeatTimer: NodeJS.Timeout | null = null;
112
104
 
113
105
  constructor(public handlerId: string, protected logger: ILogger = console) {}
114
106
 
115
107
  abstract doHeartbeat(connection: any): void;
116
108
 
117
109
  private heartbeat(connection: any) {
110
+ const timer = global.setTimeout(() => {
111
+ this.doHeartbeat(connection);
112
+ this.heartbeat(connection);
113
+ }, 5000);
114
+
118
115
  if (this.heartbeatTimer) {
119
116
  clearTimeout(this.heartbeatTimer);
120
117
  }
121
118
 
122
- this.heartbeatTimer = global.setTimeout(() => {
123
- this.doHeartbeat(connection);
124
- this.heartbeat(connection);
125
- }, 5000);
119
+ this.heartbeatTimer = timer;
126
120
  }
127
121
 
128
122
  receiveConnection(connection: IConnectionShape<Uint8Array>) {
129
123
  let clientId: string;
130
124
  this.heartbeat(connection);
131
125
 
132
- const getOrCreateChannel = (id: string, clientId: string) => {
133
- let channel = this.channelMap.get(id);
134
- if (!channel) {
135
- channel = new WSServerChannel(connection, { id, clientId, logger: this.logger });
136
- this.channelMap.set(id, channel);
137
- }
138
- return channel;
139
- };
140
-
141
126
  connection.onMessage((data: Uint8Array) => {
142
127
  let msg: ChannelMessage;
143
128
  try {
@@ -148,30 +133,23 @@ export abstract class BaseCommonChannelHandler {
148
133
  connection.send(pongMessage);
149
134
  break;
150
135
  case 'open': {
151
- const { id, path, connectionToken } = msg;
136
+ const { id, path } = msg;
152
137
  clientId = msg.clientId;
153
138
  this.logger.log(`open a new connection channel ${clientId} with path ${path}`);
154
- const channel = getOrCreateChannel(id, clientId);
155
- commonChannelPathHandler.openChannel(path, channel, clientId);
156
- channel.serverReady(connectionToken);
139
+
140
+ const channel = new WSServerChannel(connection, { id, logger: this.logger });
141
+ this.channelMap.set(id, channel);
142
+
143
+ commonChannelPathHandler.dispatchChannelOpen(path, channel, clientId);
144
+ channel.serverReady();
157
145
  break;
158
146
  }
159
147
  default: {
160
148
  const { id } = msg;
161
-
162
149
  const channel = this.channelMap.get(id);
163
150
  if (channel) {
164
151
  channel.dispatch(msg);
165
152
  } else {
166
- connection.send(
167
- stringify({
168
- kind: 'error',
169
- id,
170
- code: ErrorMessageCode.ChannelNotFound,
171
- message: `channel ${id} not found`,
172
- }),
173
- );
174
-
175
153
  this.logger.warn(`channel ${id} is not found`);
176
154
  }
177
155
  }
@@ -182,11 +160,10 @@ export abstract class BaseCommonChannelHandler {
182
160
  });
183
161
 
184
162
  connection.onceClose(() => {
185
- this.logger.log(`connection ${clientId} is closed, dispose all channels`);
186
163
  commonChannelPathHandler.disposeConnectionClientId(connection, clientId);
187
164
 
188
165
  Array.from(this.channelMap.values())
189
- .filter((channel) => channel.clientId === clientId)
166
+ .filter((channel) => channel.id.toString().indexOf(clientId) !== -1)
190
167
  .forEach((channel) => {
191
168
  channel.close(1, 'close');
192
169
  channel.dispose();