hypha-rpc 0.21.20 → 0.21.22
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/coverage/html/index.html +1 -1
- package/dist/hypha-rpc-websocket.js +136 -82
- package/dist/hypha-rpc-websocket.js.map +1 -1
- package/dist/hypha-rpc-websocket.min.js +1 -1
- package/dist/hypha-rpc-websocket.min.js.map +1 -1
- package/dist/hypha-rpc-websocket.min.mjs +1 -1
- package/dist/hypha-rpc-websocket.min.mjs.map +1 -1
- package/dist/hypha-rpc-websocket.mjs +138 -83
- package/dist/hypha-rpc-websocket.mjs.map +1 -1
- package/package.json +1 -1
- package/src/http-client.js +1 -1
- package/src/rpc.js +103 -75
- package/src/websocket-client.js +31 -6
package/coverage/html/index.html
CHANGED
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
87
87
|
Code coverage generated by
|
|
88
88
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
89
|
-
at 2026-02-
|
|
89
|
+
at 2026-02-25T19:07:57.766Z
|
|
90
90
|
</div>
|
|
91
91
|
<script src="prettify.js"></script>
|
|
92
92
|
<script>
|
|
@@ -2850,7 +2850,7 @@ class HTTPStreamingRPCConnection {
|
|
|
2850
2850
|
body: body,
|
|
2851
2851
|
});
|
|
2852
2852
|
if (response.ok) {
|
|
2853
|
-
console.debug("Token refresh requested successfully");
|
|
2853
|
+
// console.debug("Token refresh requested successfully");
|
|
2854
2854
|
} else {
|
|
2855
2855
|
console.warn(`Token refresh request failed: ${response.status}`);
|
|
2856
2856
|
}
|
|
@@ -3848,10 +3848,10 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
3848
3848
|
reasonStr.includes("Client disconnected") ||
|
|
3849
3849
|
reasonStr.includes("RPC connection closed")
|
|
3850
3850
|
) {
|
|
3851
|
-
console.debug(
|
|
3852
|
-
"Ignoring expected disconnection/method error:",
|
|
3853
|
-
reason,
|
|
3854
|
-
);
|
|
3851
|
+
// console.debug(
|
|
3852
|
+
// "Ignoring expected disconnection/method error:",
|
|
3853
|
+
// reason,
|
|
3854
|
+
// );
|
|
3855
3855
|
event.preventDefault();
|
|
3856
3856
|
return;
|
|
3857
3857
|
}
|
|
@@ -3908,6 +3908,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
3908
3908
|
this._boundHandleError = console.error;
|
|
3909
3909
|
this.on("method", this._boundHandleMethod);
|
|
3910
3910
|
this.on("error", this._boundHandleError);
|
|
3911
|
+
this.on("peer_not_found", this._handlePeerNotFound.bind(this));
|
|
3911
3912
|
|
|
3912
3913
|
(0,_utils_index_js__WEBPACK_IMPORTED_MODULE_0__.assert)(connection.emit_message && connection.on_message);
|
|
3913
3914
|
(0,_utils_index_js__WEBPACK_IMPORTED_MODULE_0__.assert)(
|
|
@@ -3919,7 +3920,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
3919
3920
|
this._connection = connection;
|
|
3920
3921
|
const onConnected = async (connectionInfo) => {
|
|
3921
3922
|
if (!this._silent && this._connection.manager_id) {
|
|
3922
|
-
console.debug("Connection established, reporting services...");
|
|
3923
|
+
// console.debug("Connection established, reporting services...");
|
|
3923
3924
|
try {
|
|
3924
3925
|
// Retry getting manager service with exponential backoff
|
|
3925
3926
|
const manager = await this.get_manager_service({
|
|
@@ -3944,9 +3945,9 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
3944
3945
|
`Timeout registering service ${service.id || "unknown"}`,
|
|
3945
3946
|
);
|
|
3946
3947
|
registeredCount++;
|
|
3947
|
-
console.debug(
|
|
3948
|
-
`Successfully registered service: ${service.id || "unknown"}`,
|
|
3949
|
-
);
|
|
3948
|
+
// console.debug(
|
|
3949
|
+
// `Successfully registered service: ${service.id || "unknown"}`,
|
|
3950
|
+
// );
|
|
3950
3951
|
} catch (serviceError) {
|
|
3951
3952
|
failedServices.push(service.id || "unknown");
|
|
3952
3953
|
if (
|
|
@@ -3998,9 +3999,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
3998
3999
|
this._clientDisconnectedSubscription.unsubscribe();
|
|
3999
4000
|
}
|
|
4000
4001
|
} catch (e) {
|
|
4001
|
-
console.debug(
|
|
4002
|
-
`Error unsubscribing old client_disconnected: ${e}`,
|
|
4003
|
-
);
|
|
4002
|
+
// console.debug(`Error unsubscribing old client_disconnected: ${e}`);
|
|
4004
4003
|
}
|
|
4005
4004
|
this._clientDisconnectedSubscription = null;
|
|
4006
4005
|
}
|
|
@@ -4016,7 +4015,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
4016
4015
|
this._boundHandleClientDisconnected = null;
|
|
4017
4016
|
}
|
|
4018
4017
|
|
|
4019
|
-
console.debug("Subscribing to client_disconnected events");
|
|
4018
|
+
// console.debug("Subscribing to client_disconnected events");
|
|
4020
4019
|
|
|
4021
4020
|
// Store handler at instance level so it can be removed later
|
|
4022
4021
|
this._boundHandleClientDisconnected = async (event) => {
|
|
@@ -4026,14 +4025,14 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
4026
4025
|
if (clientId && workspace) {
|
|
4027
4026
|
// Construct the full client path with workspace prefix
|
|
4028
4027
|
const fullClientId = `${workspace}/${clientId}`;
|
|
4029
|
-
console.debug(
|
|
4030
|
-
`Client ${fullClientId} disconnected, cleaning up sessions`,
|
|
4031
|
-
);
|
|
4028
|
+
// console.debug(
|
|
4029
|
+
// `Client ${fullClientId} disconnected, cleaning up sessions`,
|
|
4030
|
+
// );
|
|
4032
4031
|
await this._handleClientDisconnected(fullClientId);
|
|
4033
4032
|
} else if (clientId) {
|
|
4034
|
-
console.debug(
|
|
4035
|
-
`Client ${clientId} disconnected, cleaning up sessions`,
|
|
4036
|
-
);
|
|
4033
|
+
// console.debug(
|
|
4034
|
+
// `Client ${clientId} disconnected, cleaning up sessions`,
|
|
4035
|
+
// );
|
|
4037
4036
|
await this._handleClientDisconnected(clientId);
|
|
4038
4037
|
}
|
|
4039
4038
|
};
|
|
@@ -4051,19 +4050,19 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
4051
4050
|
this._boundHandleClientDisconnected,
|
|
4052
4051
|
);
|
|
4053
4052
|
|
|
4054
|
-
console.debug(
|
|
4055
|
-
"Successfully subscribed to client_disconnected events",
|
|
4056
|
-
);
|
|
4053
|
+
// console.debug(
|
|
4054
|
+
// "Successfully subscribed to client_disconnected events",
|
|
4055
|
+
// );
|
|
4057
4056
|
} else {
|
|
4058
|
-
console.debug(
|
|
4059
|
-
"Manager does not support subscribe method, skipping client_disconnected handling",
|
|
4060
|
-
);
|
|
4057
|
+
// console.debug(
|
|
4058
|
+
// "Manager does not support subscribe method, skipping client_disconnected handling",
|
|
4059
|
+
// );
|
|
4061
4060
|
this._clientDisconnectedSubscription = null;
|
|
4062
4061
|
}
|
|
4063
4062
|
} catch (subscribeError) {
|
|
4064
|
-
console.debug(
|
|
4065
|
-
`Failed to subscribe to client_disconnected events: ${subscribeError}`,
|
|
4066
|
-
);
|
|
4063
|
+
// console.debug(
|
|
4064
|
+
// `Failed to subscribe to client_disconnected events: ${subscribeError}`,
|
|
4065
|
+
// );
|
|
4067
4066
|
this._clientDisconnectedSubscription = null;
|
|
4068
4067
|
}
|
|
4069
4068
|
} catch (managerError) {
|
|
@@ -4369,7 +4368,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
4369
4368
|
this._clientDisconnectedSubscription.unsubscribe();
|
|
4370
4369
|
}
|
|
4371
4370
|
} catch (e) {
|
|
4372
|
-
console.debug(`Error unsubscribing client_disconnected: ${e}`);
|
|
4371
|
+
// console.debug(`Error unsubscribing client_disconnected: ${e}`);
|
|
4373
4372
|
}
|
|
4374
4373
|
this._clientDisconnectedSubscription = null;
|
|
4375
4374
|
}
|
|
@@ -4392,13 +4391,13 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
4392
4391
|
try {
|
|
4393
4392
|
task.cancel();
|
|
4394
4393
|
} catch (e) {
|
|
4395
|
-
console.debug(`Error canceling background task: ${e}`);
|
|
4394
|
+
// console.debug(`Error canceling background task: ${e}`);
|
|
4396
4395
|
}
|
|
4397
4396
|
}
|
|
4398
4397
|
}
|
|
4399
4398
|
this._background_tasks.clear();
|
|
4400
4399
|
} catch (e) {
|
|
4401
|
-
console.debug(`Error cleaning up background tasks: ${e}`);
|
|
4400
|
+
// console.debug(`Error cleaning up background tasks: ${e}`);
|
|
4402
4401
|
}
|
|
4403
4402
|
|
|
4404
4403
|
// Clear session sweep interval
|
|
@@ -4411,11 +4410,11 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
4411
4410
|
try {
|
|
4412
4411
|
this._connection = null;
|
|
4413
4412
|
this._emit_message = function () {
|
|
4414
|
-
console.debug("RPC connection closed, ignoring message");
|
|
4413
|
+
// console.debug("RPC connection closed, ignoring message");
|
|
4415
4414
|
return Promise.reject(new Error("Connection is closed"));
|
|
4416
4415
|
};
|
|
4417
4416
|
} catch (e) {
|
|
4418
|
-
console.debug(`Error during connection cleanup: ${e}`);
|
|
4417
|
+
// console.debug(`Error during connection cleanup: ${e}`);
|
|
4419
4418
|
}
|
|
4420
4419
|
|
|
4421
4420
|
this._fire("disconnected");
|
|
@@ -4423,15 +4422,15 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
4423
4422
|
|
|
4424
4423
|
async _handleClientDisconnected(clientId) {
|
|
4425
4424
|
try {
|
|
4426
|
-
console.debug(`Handling disconnection for client: ${clientId}`);
|
|
4425
|
+
// console.debug(`Handling disconnection for client: ${clientId}`);
|
|
4427
4426
|
|
|
4428
4427
|
// Clean up all sessions for the disconnected client
|
|
4429
4428
|
const sessionsCleaned = this._cleanupSessionsForClient(clientId);
|
|
4430
4429
|
|
|
4431
4430
|
if (sessionsCleaned > 0) {
|
|
4432
|
-
console.debug(
|
|
4433
|
-
`Cleaned up ${sessionsCleaned} sessions for disconnected client: ${clientId}`,
|
|
4434
|
-
);
|
|
4431
|
+
// console.debug(
|
|
4432
|
+
// `Cleaned up ${sessionsCleaned} sessions for disconnected client: ${clientId}`,
|
|
4433
|
+
// );
|
|
4435
4434
|
}
|
|
4436
4435
|
|
|
4437
4436
|
// Fire an event to notify about the client disconnection
|
|
@@ -4446,6 +4445,35 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
4446
4445
|
}
|
|
4447
4446
|
}
|
|
4448
4447
|
|
|
4448
|
+
_handlePeerNotFound(data) {
|
|
4449
|
+
/**
|
|
4450
|
+
* Handle server notification that target peer is not connected.
|
|
4451
|
+
*
|
|
4452
|
+
* When the server detects that an RPC message targets a disconnected
|
|
4453
|
+
* client, it sends back a 'peer_not_found' message instead of silently
|
|
4454
|
+
* dropping it. This allows pending calls to fail immediately.
|
|
4455
|
+
*/
|
|
4456
|
+
const sessionId = data.session;
|
|
4457
|
+
const peerId = data.peer_id || data.from || "unknown";
|
|
4458
|
+
const errorMsg = data.error || `Peer ${peerId} is not connected`;
|
|
4459
|
+
// console.debug(`Peer not found: ${peerId} (session=${sessionId})`);
|
|
4460
|
+
|
|
4461
|
+
// Reject the specific pending call identified by sessionId
|
|
4462
|
+
if (sessionId) {
|
|
4463
|
+
const session = this._object_store[sessionId];
|
|
4464
|
+
if (session && typeof session === "object") {
|
|
4465
|
+
this._cleanupSessionEntry(session, errorMsg);
|
|
4466
|
+
delete this._object_store[sessionId];
|
|
4467
|
+
this._removeFromTargetIdIndex(sessionId);
|
|
4468
|
+
}
|
|
4469
|
+
}
|
|
4470
|
+
|
|
4471
|
+
// Also clean up all other sessions targeting this peer
|
|
4472
|
+
if (peerId) {
|
|
4473
|
+
this._cleanupSessionsForClient(peerId);
|
|
4474
|
+
}
|
|
4475
|
+
}
|
|
4476
|
+
|
|
4449
4477
|
_removeFromTargetIdIndex(sessionId) {
|
|
4450
4478
|
/**
|
|
4451
4479
|
* Remove a session from the target_id index.
|
|
@@ -4480,7 +4508,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
4480
4508
|
try {
|
|
4481
4509
|
session.reject(new Error(rejectReason));
|
|
4482
4510
|
} catch (e) {
|
|
4483
|
-
console.debug(`Error rejecting session: ${e}`);
|
|
4511
|
+
// console.debug(`Error rejecting session: ${e}`);
|
|
4484
4512
|
}
|
|
4485
4513
|
}
|
|
4486
4514
|
if (session.heartbeat_task) {
|
|
@@ -4519,7 +4547,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
4519
4547
|
this._cleanupSessionEntry(session, reason);
|
|
4520
4548
|
delete this._object_store[sessionKey];
|
|
4521
4549
|
sessionsCleaned++;
|
|
4522
|
-
console.debug(`Cleaned up session: ${sessionKey}`);
|
|
4550
|
+
// console.debug(`Cleaned up session: ${sessionKey}`);
|
|
4523
4551
|
}
|
|
4524
4552
|
|
|
4525
4553
|
delete this._targetIdIndex[clientId];
|
|
@@ -4555,7 +4583,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
4555
4583
|
|
|
4556
4584
|
_cleanupOnDisconnect() {
|
|
4557
4585
|
try {
|
|
4558
|
-
console.debug("Cleaning up all sessions due to local RPC disconnection");
|
|
4586
|
+
// console.debug("Cleaning up all sessions due to local RPC disconnection");
|
|
4559
4587
|
|
|
4560
4588
|
const keysToDelete = [];
|
|
4561
4589
|
for (const key of Object.keys(this._object_store)) {
|
|
@@ -4585,7 +4613,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
4585
4613
|
try {
|
|
4586
4614
|
await connection.disconnect();
|
|
4587
4615
|
} catch (e) {
|
|
4588
|
-
console.debug(`Error disconnecting underlying connection: ${e}`);
|
|
4616
|
+
// console.debug(`Error disconnecting underlying connection: ${e}`);
|
|
4589
4617
|
}
|
|
4590
4618
|
}
|
|
4591
4619
|
}
|
|
@@ -5079,14 +5107,14 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5079
5107
|
* Clean session management - all logic in one place.
|
|
5080
5108
|
*/
|
|
5081
5109
|
if (!session_id) {
|
|
5082
|
-
console.debug("Cannot cleanup session: session_id is empty");
|
|
5110
|
+
// console.debug("Cannot cleanup session: session_id is empty");
|
|
5083
5111
|
return;
|
|
5084
5112
|
}
|
|
5085
5113
|
|
|
5086
5114
|
try {
|
|
5087
5115
|
const store = this._get_session_store(session_id, false);
|
|
5088
5116
|
if (!store) {
|
|
5089
|
-
console.debug(`Session ${session_id} not found for cleanup`);
|
|
5117
|
+
// console.debug(`Session ${session_id} not found for cleanup`);
|
|
5090
5118
|
return;
|
|
5091
5119
|
}
|
|
5092
5120
|
|
|
@@ -5104,9 +5132,9 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5104
5132
|
promise_manager.settle();
|
|
5105
5133
|
}
|
|
5106
5134
|
should_cleanup = true;
|
|
5107
|
-
console.debug(
|
|
5108
|
-
`Promise session ${session_id} settled and marked for cleanup`,
|
|
5109
|
-
);
|
|
5135
|
+
// console.debug(
|
|
5136
|
+
// `Promise session ${session_id} settled and marked for cleanup`,
|
|
5137
|
+
// );
|
|
5110
5138
|
}
|
|
5111
5139
|
} catch (e) {
|
|
5112
5140
|
console.warn(
|
|
@@ -5124,9 +5152,9 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5124
5152
|
Object.keys(store._callbacks).includes(callback_name)
|
|
5125
5153
|
) {
|
|
5126
5154
|
should_cleanup = true;
|
|
5127
|
-
console.debug(
|
|
5128
|
-
`Regular session ${session_id} marked for cleanup after ${callback_name}`,
|
|
5129
|
-
);
|
|
5155
|
+
// console.debug(
|
|
5156
|
+
// `Regular session ${session_id} marked for cleanup after ${callback_name}`,
|
|
5157
|
+
// );
|
|
5130
5158
|
}
|
|
5131
5159
|
}
|
|
5132
5160
|
|
|
@@ -5148,7 +5176,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5148
5176
|
|
|
5149
5177
|
const store = this._get_session_store(session_id, false);
|
|
5150
5178
|
if (!store) {
|
|
5151
|
-
console.debug(`Session ${session_id} already cleaned up`);
|
|
5179
|
+
// console.debug(`Session ${session_id} already cleaned up`);
|
|
5152
5180
|
return;
|
|
5153
5181
|
}
|
|
5154
5182
|
|
|
@@ -5190,9 +5218,9 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5190
5218
|
for (let i = 0; i < levels.length - 1; i++) {
|
|
5191
5219
|
const level = levels[i];
|
|
5192
5220
|
if (!current_store[level]) {
|
|
5193
|
-
console.debug(
|
|
5194
|
-
`Session path ${session_id} not found at level ${level}`,
|
|
5195
|
-
);
|
|
5221
|
+
// console.debug(
|
|
5222
|
+
// `Session path ${session_id} not found at level ${level}`,
|
|
5223
|
+
// );
|
|
5196
5224
|
return;
|
|
5197
5225
|
}
|
|
5198
5226
|
current_store = current_store[level];
|
|
@@ -5202,7 +5230,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5202
5230
|
const final_key = levels[levels.length - 1];
|
|
5203
5231
|
if (current_store[final_key]) {
|
|
5204
5232
|
delete current_store[final_key];
|
|
5205
|
-
console.debug(`Cleaned up session ${session_id}`);
|
|
5233
|
+
// console.debug(`Cleaned up session ${session_id}`);
|
|
5206
5234
|
|
|
5207
5235
|
// Clean up empty parent containers
|
|
5208
5236
|
this._cleanup_empty_containers(levels.slice(0, -1));
|
|
@@ -5240,9 +5268,9 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5240
5268
|
Object.keys(container).length === 0
|
|
5241
5269
|
) {
|
|
5242
5270
|
delete current_store[container_key];
|
|
5243
|
-
console.debug(
|
|
5244
|
-
`Cleaned up empty container at depth ${depth}: ${path_levels.slice(0, depth + 1).join(".")}`,
|
|
5245
|
-
);
|
|
5271
|
+
// console.debug(
|
|
5272
|
+
// `Cleaned up empty container at depth ${depth}: ${path_levels.slice(0, depth + 1).join(".")}`,
|
|
5273
|
+
// );
|
|
5246
5274
|
} else {
|
|
5247
5275
|
// Container is not empty, stop cleanup
|
|
5248
5276
|
break;
|
|
@@ -5317,7 +5345,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5317
5345
|
* Force cleanup all sessions (for testing purposes).
|
|
5318
5346
|
*/
|
|
5319
5347
|
if (!this._object_store) {
|
|
5320
|
-
console.debug("Force cleaning up 0 sessions");
|
|
5348
|
+
// console.debug("Force cleaning up 0 sessions");
|
|
5321
5349
|
return;
|
|
5322
5350
|
}
|
|
5323
5351
|
|
|
@@ -5347,7 +5375,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5347
5375
|
// Clear the target_id index since all sessions are removed
|
|
5348
5376
|
this._targetIdIndex = {};
|
|
5349
5377
|
|
|
5350
|
-
console.debug(`Force cleaning up ${cleaned_count} sessions`);
|
|
5378
|
+
// console.debug(`Force cleaning up ${cleaned_count} sessions`);
|
|
5351
5379
|
}
|
|
5352
5380
|
|
|
5353
5381
|
_sweepStaleSessions() {
|
|
@@ -5383,7 +5411,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5383
5411
|
}
|
|
5384
5412
|
}
|
|
5385
5413
|
if (swept > 0) {
|
|
5386
|
-
console.debug(`Swept ${swept} stale session(s)`);
|
|
5414
|
+
// console.debug(`Swept ${swept} stale session(s)`);
|
|
5387
5415
|
}
|
|
5388
5416
|
}
|
|
5389
5417
|
|
|
@@ -5405,7 +5433,7 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5405
5433
|
},
|
|
5406
5434
|
settle: () => {
|
|
5407
5435
|
// Promise is settled (resolved or rejected)
|
|
5408
|
-
console.debug("Promise settled");
|
|
5436
|
+
// console.debug("Promise settled");
|
|
5409
5437
|
},
|
|
5410
5438
|
};
|
|
5411
5439
|
}
|
|
@@ -5676,9 +5704,9 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5676
5704
|
// Clean up target_id index before deleting the session
|
|
5677
5705
|
self._removeFromTargetIdIndex(local_session_id);
|
|
5678
5706
|
delete self._object_store[local_session_id];
|
|
5679
|
-
console.debug(
|
|
5680
|
-
`Cleaned up session ${local_session_id} after timeout`,
|
|
5681
|
-
);
|
|
5707
|
+
// console.debug(
|
|
5708
|
+
// `Cleaned up session ${local_session_id} after timeout`,
|
|
5709
|
+
// );
|
|
5682
5710
|
}
|
|
5683
5711
|
};
|
|
5684
5712
|
|
|
@@ -5961,9 +5989,9 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5961
5989
|
} catch (e) {
|
|
5962
5990
|
// Clean promise method detection - TYPE-BASED, not string-based
|
|
5963
5991
|
if (this._is_promise_method_call(data["method"])) {
|
|
5964
|
-
console.debug(
|
|
5965
|
-
`Promise method ${data["method"]} not available (detected by session type), ignoring: ${method_name}`,
|
|
5966
|
-
);
|
|
5992
|
+
// console.debug(
|
|
5993
|
+
// `Promise method ${data["method"]} not available (detected by session type), ignoring: ${method_name}`,
|
|
5994
|
+
// );
|
|
5967
5995
|
return;
|
|
5968
5996
|
}
|
|
5969
5997
|
|
|
@@ -5973,18 +6001,18 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5973
6001
|
const session_id = method_parts[0];
|
|
5974
6002
|
// Check if the session exists but the specific method doesn't
|
|
5975
6003
|
if (session_id in this._object_store) {
|
|
5976
|
-
console.debug(
|
|
5977
|
-
`Session ${session_id} exists but method ${data["method"]} not found, likely expired callback: ${method_name}`,
|
|
5978
|
-
);
|
|
6004
|
+
// console.debug(
|
|
6005
|
+
// `Session ${session_id} exists but method ${data["method"]} not found, likely expired callback: ${method_name}`,
|
|
6006
|
+
// );
|
|
5979
6007
|
// For expired callbacks, don't throw an exception, just log and return
|
|
5980
6008
|
if (typeof reject === "function") {
|
|
5981
6009
|
reject(new Error(`Method expired or not found: ${method_name}`));
|
|
5982
6010
|
}
|
|
5983
6011
|
return;
|
|
5984
6012
|
} else {
|
|
5985
|
-
console.debug(
|
|
5986
|
-
`Session ${session_id} not found for method ${data["method"]}, likely cleaned up: ${method_name}`,
|
|
5987
|
-
);
|
|
6013
|
+
// console.debug(
|
|
6014
|
+
// `Session ${session_id} not found for method ${data["method"]}, likely cleaned up: ${method_name}`,
|
|
6015
|
+
// );
|
|
5988
6016
|
// For cleaned up sessions, just log and return without throwing
|
|
5989
6017
|
if (typeof reject === "function") {
|
|
5990
6018
|
reject(new Error(`Session not found: ${method_name}`));
|
|
@@ -5993,9 +6021,9 @@ class RPC extends _utils_index_js__WEBPACK_IMPORTED_MODULE_0__.MessageEmitter {
|
|
|
5993
6021
|
}
|
|
5994
6022
|
}
|
|
5995
6023
|
|
|
5996
|
-
console.debug(
|
|
5997
|
-
`Failed to find method ${method_name} at ${this._client_id}`,
|
|
5998
|
-
);
|
|
6024
|
+
// console.debug(
|
|
6025
|
+
// `Failed to find method ${method_name} at ${this._client_id}`,
|
|
6026
|
+
// );
|
|
5999
6027
|
const error = new Error(
|
|
6000
6028
|
`Method not found: ${method_name} at ${this._client_id}`,
|
|
6001
6029
|
);
|
|
@@ -9938,6 +9966,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
9938
9966
|
/* harmony export */ HTTPStreamingRPCConnection: () => (/* reexport safe */ _http_client_js__WEBPACK_IMPORTED_MODULE_5__.HTTPStreamingRPCConnection),
|
|
9939
9967
|
/* harmony export */ LocalWebSocket: () => (/* binding */ LocalWebSocket),
|
|
9940
9968
|
/* harmony export */ RPC: () => (/* reexport safe */ _rpc_js__WEBPACK_IMPORTED_MODULE_0__.RPC),
|
|
9969
|
+
/* harmony export */ WebsocketRPCConnection: () => (/* binding */ WebsocketRPCConnection),
|
|
9941
9970
|
/* harmony export */ connectToServer: () => (/* binding */ connectToServer),
|
|
9942
9971
|
/* harmony export */ connectToServerHTTP: () => (/* reexport safe */ _http_client_js__WEBPACK_IMPORTED_MODULE_5__.connectToServerHTTP),
|
|
9943
9972
|
/* harmony export */ decryptPayload: () => (/* reexport safe */ _crypto_js__WEBPACK_IMPORTED_MODULE_1__.decryptPayload),
|
|
@@ -10019,6 +10048,7 @@ class WebsocketRPCConnection {
|
|
|
10019
10048
|
this._reconnect_timeouts = new Set(); // Track reconnection timeouts
|
|
10020
10049
|
this._additional_headers = additional_headers;
|
|
10021
10050
|
this._reconnecting = false; // Mutex to prevent overlapping reconnection attempts
|
|
10051
|
+
this._closedDuringReconnect = false; // Flag for close events during reconnection
|
|
10022
10052
|
this._disconnectedNotified = false;
|
|
10023
10053
|
}
|
|
10024
10054
|
|
|
@@ -10261,7 +10291,9 @@ class WebsocketRPCConnection {
|
|
|
10261
10291
|
this._websocket.onclose = this._handle_close.bind(this);
|
|
10262
10292
|
|
|
10263
10293
|
if (this._handle_connected) {
|
|
10264
|
-
|
|
10294
|
+
// Await async callbacks so errors (e.g. service re-registration
|
|
10295
|
+
// failures) propagate instead of becoming unhandled rejections.
|
|
10296
|
+
await this._handle_connected(this.connection_info);
|
|
10265
10297
|
}
|
|
10266
10298
|
return this.connection_info;
|
|
10267
10299
|
} catch (error) {
|
|
@@ -10327,9 +10359,10 @@ class WebsocketRPCConnection {
|
|
|
10327
10359
|
// Notify the RPC layer immediately so it can reject pending calls
|
|
10328
10360
|
this._notifyDisconnected(event.reason);
|
|
10329
10361
|
|
|
10330
|
-
//
|
|
10362
|
+
// If a reconnection is already in progress, signal it so the
|
|
10363
|
+
// reconnect loop can detect that the newly-opened socket died and retry.
|
|
10331
10364
|
if (this._reconnecting) {
|
|
10332
|
-
|
|
10365
|
+
this._closedDuringReconnect = true;
|
|
10333
10366
|
return;
|
|
10334
10367
|
}
|
|
10335
10368
|
this._reconnecting = true;
|
|
@@ -10351,6 +10384,10 @@ class WebsocketRPCConnection {
|
|
|
10351
10384
|
console.warn(
|
|
10352
10385
|
`Reconnecting to ${this._server_url.split("?")[0]} (attempt #${retry})`,
|
|
10353
10386
|
);
|
|
10387
|
+
// Reset the flag before each attempt so we can detect new close
|
|
10388
|
+
// events that arrive while open() and the settle period run.
|
|
10389
|
+
this._closedDuringReconnect = false;
|
|
10390
|
+
|
|
10354
10391
|
// Open the connection, this will trigger the on_connected callback
|
|
10355
10392
|
await this.open();
|
|
10356
10393
|
|
|
@@ -10359,6 +10396,22 @@ class WebsocketRPCConnection {
|
|
|
10359
10396
|
// which includes re-registering all services to the server
|
|
10360
10397
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
10361
10398
|
|
|
10399
|
+
// Check if the WebSocket died during the settle period.
|
|
10400
|
+
// This handles the race where _handle_close fires while
|
|
10401
|
+
// _reconnecting is true and sets _closedDuringReconnect.
|
|
10402
|
+
if (
|
|
10403
|
+
this._closedDuringReconnect ||
|
|
10404
|
+
!this._websocket ||
|
|
10405
|
+
this._websocket.readyState !== WebSocket.OPEN
|
|
10406
|
+
) {
|
|
10407
|
+
console.warn(
|
|
10408
|
+
"WebSocket closed during reconnection settle period, retrying...",
|
|
10409
|
+
);
|
|
10410
|
+
this._closedDuringReconnect = false;
|
|
10411
|
+
// Fall through to the retry logic below
|
|
10412
|
+
throw new Error("Connection lost during reconnection settle");
|
|
10413
|
+
}
|
|
10414
|
+
|
|
10362
10415
|
console.warn(
|
|
10363
10416
|
`Successfully reconnected to server ${this._server_url} (services re-registered)`,
|
|
10364
10417
|
);
|
|
@@ -10402,9 +10455,7 @@ class WebsocketRPCConnection {
|
|
|
10402
10455
|
const jitter = (Math.random() * 2 - 1) * maxJitter * delay;
|
|
10403
10456
|
const finalDelay = Math.max(100, delay + jitter);
|
|
10404
10457
|
|
|
10405
|
-
console.debug(
|
|
10406
|
-
`Waiting ${(finalDelay / 1000).toFixed(2)}s before next reconnection attempt`,
|
|
10407
|
-
);
|
|
10458
|
+
// console.debug(`Waiting ${(finalDelay / 1000).toFixed(2)}s before next reconnection attempt`);
|
|
10408
10459
|
|
|
10409
10460
|
// Track the reconnection timeout to prevent leaks
|
|
10410
10461
|
const timeoutId = setTimeout(async () => {
|
|
@@ -10469,6 +10520,7 @@ class WebsocketRPCConnection {
|
|
|
10469
10520
|
disconnect(reason) {
|
|
10470
10521
|
this._closed = true;
|
|
10471
10522
|
this._reconnecting = false;
|
|
10523
|
+
this._closedDuringReconnect = false;
|
|
10472
10524
|
// Ensure websocket is closed if it exists and is not already closed or closing
|
|
10473
10525
|
if (
|
|
10474
10526
|
this._websocket &&
|
|
@@ -11143,6 +11195,8 @@ class LocalWebSocket {
|
|
|
11143
11195
|
// hypha-core's deno build does: import { hyphaWebsocketClient } from 'hypha-rpc'
|
|
11144
11196
|
// The UMD build wraps everything under this name via webpack's `library` option,
|
|
11145
11197
|
// but the ESM build exports flat, so we need this explicit re-export.
|
|
11198
|
+
|
|
11199
|
+
|
|
11146
11200
|
const hyphaWebsocketClient = {
|
|
11147
11201
|
RPC: _rpc_js__WEBPACK_IMPORTED_MODULE_0__.RPC,
|
|
11148
11202
|
API_VERSION: _rpc_js__WEBPACK_IMPORTED_MODULE_0__.API_VERSION,
|