hypha-rpc 0.20.85 → 0.20.87
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/hypha-rpc-websocket.js +79 -21
- package/dist/hypha-rpc-websocket.min.js +1 -1
- package/dist/hypha-rpc-websocket.min.mjs +1 -1
- package/dist/hypha-rpc-websocket.mjs +79 -21
- package/package.json +1 -1
- package/src/rpc.js +57 -10
- package/src/websocket-client.js +22 -11
|
@@ -51,6 +51,31 @@ function _appendBuffer(buffer1, buffer2) {
|
|
|
51
51
|
return tmp.buffer;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Wrap a promise with a timeout.
|
|
56
|
+
* @param {Promise} promise - The promise to wrap.
|
|
57
|
+
* @param {number} timeoutMs - The timeout in milliseconds.
|
|
58
|
+
* @param {string} message - Optional error message for timeout.
|
|
59
|
+
* @returns {Promise} - The wrapped promise that will reject on timeout.
|
|
60
|
+
*/
|
|
61
|
+
function withTimeout(promise, timeoutMs, message = "Operation timed out") {
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
const timeoutId = setTimeout(() => {
|
|
64
|
+
reject(new Error(`TimeoutError: ${message}`));
|
|
65
|
+
}, timeoutMs);
|
|
66
|
+
|
|
67
|
+
promise
|
|
68
|
+
.then((result) => {
|
|
69
|
+
clearTimeout(timeoutId);
|
|
70
|
+
resolve(result);
|
|
71
|
+
})
|
|
72
|
+
.catch((error) => {
|
|
73
|
+
clearTimeout(timeoutId);
|
|
74
|
+
reject(error);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
54
79
|
function indexObject(obj, is) {
|
|
55
80
|
if (!is) throw new Error("undefined index");
|
|
56
81
|
if (typeof is === "string") return indexObject(obj, is.split("."));
|
|
@@ -418,19 +443,35 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
418
443
|
let registeredCount = 0;
|
|
419
444
|
const failedServices = [];
|
|
420
445
|
|
|
446
|
+
// Use timeout for service registration to prevent hanging
|
|
447
|
+
const serviceRegistrationTimeout = this._method_timeout || 30000;
|
|
448
|
+
|
|
421
449
|
for (let service of services) {
|
|
422
450
|
try {
|
|
423
451
|
const serviceInfo = this._extract_service_info(service);
|
|
424
|
-
await
|
|
452
|
+
await withTimeout(
|
|
453
|
+
manager.registerService(serviceInfo),
|
|
454
|
+
serviceRegistrationTimeout,
|
|
455
|
+
`Timeout registering service ${service.id || "unknown"}`,
|
|
456
|
+
);
|
|
425
457
|
registeredCount++;
|
|
426
458
|
console.debug(
|
|
427
459
|
`Successfully registered service: ${service.id || "unknown"}`,
|
|
428
460
|
);
|
|
429
461
|
} catch (serviceError) {
|
|
430
462
|
failedServices.push(service.id || "unknown");
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
463
|
+
if (
|
|
464
|
+
serviceError.message &&
|
|
465
|
+
serviceError.message.includes("TimeoutError")
|
|
466
|
+
) {
|
|
467
|
+
console.error(
|
|
468
|
+
`Timeout registering service ${service.id || "unknown"}`,
|
|
469
|
+
);
|
|
470
|
+
} else {
|
|
471
|
+
console.error(
|
|
472
|
+
`Failed to register service ${service.id || "unknown"}: ${serviceError}`,
|
|
473
|
+
);
|
|
474
|
+
}
|
|
434
475
|
}
|
|
435
476
|
}
|
|
436
477
|
|
|
@@ -478,10 +519,12 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
478
519
|
}
|
|
479
520
|
};
|
|
480
521
|
|
|
481
|
-
// Subscribe to the event topic first
|
|
482
|
-
this._clientDisconnectedSubscription = await
|
|
483
|
-
"client_disconnected",
|
|
484
|
-
|
|
522
|
+
// Subscribe to the event topic first with timeout
|
|
523
|
+
this._clientDisconnectedSubscription = await withTimeout(
|
|
524
|
+
manager.subscribe(["client_disconnected"]),
|
|
525
|
+
serviceRegistrationTimeout,
|
|
526
|
+
"Timeout subscribing to client_disconnected events",
|
|
527
|
+
);
|
|
485
528
|
|
|
486
529
|
// Then register the local event handler
|
|
487
530
|
this.on("client_disconnected", handleClientDisconnected);
|
|
@@ -1232,7 +1275,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
1232
1275
|
config.workspace || this._local_workspace || this._connection.workspace;
|
|
1233
1276
|
if (!config.workspace) {
|
|
1234
1277
|
throw new Error(
|
|
1235
|
-
"Workspace is not set. Please ensure the connection has a workspace or set local_workspace."
|
|
1278
|
+
"Workspace is not set. Please ensure the connection has a workspace or set local_workspace.",
|
|
1236
1279
|
);
|
|
1237
1280
|
}
|
|
1238
1281
|
const skipContext = config.require_context;
|
|
@@ -2654,7 +2697,11 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
2654
2697
|
local_workspace,
|
|
2655
2698
|
),
|
|
2656
2699
|
};
|
|
2657
|
-
} else if (
|
|
2700
|
+
} else if (
|
|
2701
|
+
aObject.constructor === Object ||
|
|
2702
|
+
Array.isArray(aObject) ||
|
|
2703
|
+
aObject instanceof RemoteService
|
|
2704
|
+
) {
|
|
2658
2705
|
bObject = isarray ? [] : {};
|
|
2659
2706
|
const keys = Object.keys(aObject);
|
|
2660
2707
|
for (let k of keys) {
|
|
@@ -6278,12 +6325,22 @@ class WebsocketRPCConnection {
|
|
|
6278
6325
|
}
|
|
6279
6326
|
} catch (e) {
|
|
6280
6327
|
if (`${e}`.includes("ConnectionAbortedError:")) {
|
|
6281
|
-
console.warn("
|
|
6328
|
+
console.warn("Server refused to reconnect:", e);
|
|
6329
|
+
// Mark as closed and notify the application
|
|
6330
|
+
this._closed = true;
|
|
6331
|
+
if (this._handle_disconnected) {
|
|
6332
|
+
this._handle_disconnected(`Server refused reconnection: ${e}`);
|
|
6333
|
+
}
|
|
6282
6334
|
return;
|
|
6283
6335
|
} else if (`${e}`.includes("NotImplementedError:")) {
|
|
6284
6336
|
console.error(
|
|
6285
6337
|
`${e}\nIt appears that you are trying to connect to a hypha server that is older than 0.20.0, please upgrade the hypha server or use the websocket client in imjoy-rpc(https://www.npmjs.com/package/imjoy-rpc) instead`,
|
|
6286
6338
|
);
|
|
6339
|
+
// Mark as closed to prevent further reconnection attempts
|
|
6340
|
+
this._closed = true;
|
|
6341
|
+
if (this._handle_disconnected) {
|
|
6342
|
+
this._handle_disconnected(`Server too old: ${e}`);
|
|
6343
|
+
}
|
|
6287
6344
|
return;
|
|
6288
6345
|
}
|
|
6289
6346
|
|
|
@@ -6337,21 +6394,20 @@ class WebsocketRPCConnection {
|
|
|
6337
6394
|
await reconnect();
|
|
6338
6395
|
} else {
|
|
6339
6396
|
console.error(
|
|
6340
|
-
`Failed to reconnect after ${MAX_RETRY} attempts, giving up
|
|
6397
|
+
`Failed to reconnect after ${MAX_RETRY} attempts, giving up.`,
|
|
6341
6398
|
);
|
|
6399
|
+
// Mark as closed to prevent further reconnection attempts
|
|
6400
|
+
this._closed = true;
|
|
6342
6401
|
// Notify about max retry exceeded
|
|
6343
6402
|
if (this._handle_disconnected) {
|
|
6344
6403
|
this._handle_disconnected(
|
|
6345
6404
|
"Max reconnection attempts exceeded",
|
|
6346
6405
|
);
|
|
6347
6406
|
}
|
|
6348
|
-
//
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
);
|
|
6353
|
-
process.exit(1);
|
|
6354
|
-
}
|
|
6407
|
+
// Note: We intentionally do NOT call process.exit() here.
|
|
6408
|
+
// Instead, we mark the connection as closed and let the
|
|
6409
|
+
// application handle the failure through the disconnected
|
|
6410
|
+
// handler or by checking connection state.
|
|
6355
6411
|
}
|
|
6356
6412
|
}, finalDelay);
|
|
6357
6413
|
this._reconnect_timeouts.add(timeoutId);
|
|
@@ -6468,7 +6524,7 @@ async function logout(config) {
|
|
|
6468
6524
|
if (!svc.logout) {
|
|
6469
6525
|
throw new Error(
|
|
6470
6526
|
"Logout is not supported by this server. " +
|
|
6471
|
-
|
|
6527
|
+
"Please upgrade the Hypha server to a version that supports logout.",
|
|
6472
6528
|
);
|
|
6473
6529
|
}
|
|
6474
6530
|
|
|
@@ -6476,7 +6532,9 @@ async function logout(config) {
|
|
|
6476
6532
|
if (callback) {
|
|
6477
6533
|
await callback(context);
|
|
6478
6534
|
} else {
|
|
6479
|
-
console.log(
|
|
6535
|
+
console.log(
|
|
6536
|
+
`Please open your browser to logout at ${context.logout_url}`,
|
|
6537
|
+
);
|
|
6480
6538
|
}
|
|
6481
6539
|
return context;
|
|
6482
6540
|
} catch (error) {
|