@ricsam/isolate-daemon 0.1.20 → 0.1.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/dist/cjs/connection.cjs +122 -11
- package/dist/cjs/connection.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/connection.mjs +122 -11
- package/dist/mjs/connection.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/types/types.d.ts +4 -0
- package/package.json +6 -6
package/dist/cjs/connection.cjs
CHANGED
|
@@ -47,6 +47,26 @@ var import_isolate_protocol = require("@ricsam/isolate-protocol");
|
|
|
47
47
|
var import_callback_fs_handler = require("./callback-fs-handler.cjs");
|
|
48
48
|
var import_isolate_runtime = require("@ricsam/isolate-runtime");
|
|
49
49
|
var LINKER_CONFLICT_ERROR = "Module is currently being linked by another linker";
|
|
50
|
+
var NULL_BODY_STATUSES = new Set([101, 103, 204, 205, 304]);
|
|
51
|
+
var DEFAULT_CALLBACK_TIMEOUT_MS = 120000;
|
|
52
|
+
var FETCH_CALLBACK_TIMEOUT_MS = 35000;
|
|
53
|
+
function createAbortError(reason = "The operation was aborted") {
|
|
54
|
+
if (typeof DOMException !== "undefined") {
|
|
55
|
+
return new DOMException(reason, "AbortError");
|
|
56
|
+
}
|
|
57
|
+
const error = new Error(reason);
|
|
58
|
+
error.name = "AbortError";
|
|
59
|
+
return error;
|
|
60
|
+
}
|
|
61
|
+
function sendCallbackAbortMessage(connection, targetRequestId, reason) {
|
|
62
|
+
const abortMessage = {
|
|
63
|
+
type: import_isolate_protocol.MessageType.CALLBACK_ABORT,
|
|
64
|
+
requestId: connection.nextRequestId++,
|
|
65
|
+
targetRequestId,
|
|
66
|
+
reason
|
|
67
|
+
};
|
|
68
|
+
sendMessage(connection.socket, abortMessage);
|
|
69
|
+
}
|
|
50
70
|
function getErrorText(error) {
|
|
51
71
|
if (error instanceof Error) {
|
|
52
72
|
const cause = error.cause;
|
|
@@ -121,6 +141,7 @@ function handleConnection(socket, state) {
|
|
|
121
141
|
}
|
|
122
142
|
}
|
|
123
143
|
for (const [, pending] of connection.pendingCallbacks) {
|
|
144
|
+
pending.cleanup?.();
|
|
124
145
|
pending.reject(new Error("Connection closed"));
|
|
125
146
|
}
|
|
126
147
|
connection.pendingCallbacks.clear();
|
|
@@ -454,14 +475,14 @@ async function waitForConnection(callbackContext) {
|
|
|
454
475
|
}
|
|
455
476
|
throw new Error("No connection available and no reconnection pending");
|
|
456
477
|
}
|
|
457
|
-
async function invokeCallbackWithReconnect(callbackContext, getCallbackId, args, label, invokeClientCallback) {
|
|
478
|
+
async function invokeCallbackWithReconnect(callbackContext, getCallbackId, args, label, invokeClientCallback, options) {
|
|
458
479
|
const conn = await waitForConnection(callbackContext);
|
|
459
480
|
const cbId = getCallbackId();
|
|
460
481
|
if (cbId === undefined) {
|
|
461
482
|
throw new Error(`${label} callback not available`);
|
|
462
483
|
}
|
|
463
484
|
try {
|
|
464
|
-
return await invokeClientCallback(conn, cbId, args);
|
|
485
|
+
return await invokeClientCallback(conn, cbId, args, options);
|
|
465
486
|
} catch (err) {
|
|
466
487
|
if (callbackContext.reconnectionPromise && !callbackContext.connection) {
|
|
467
488
|
const newConn = await callbackContext.reconnectionPromise.promise;
|
|
@@ -469,7 +490,7 @@ async function invokeCallbackWithReconnect(callbackContext, getCallbackId, args,
|
|
|
469
490
|
if (newCbId === undefined) {
|
|
470
491
|
throw new Error(`${label} callback not available after reconnection`);
|
|
471
492
|
}
|
|
472
|
-
return invokeClientCallback(newConn, newCbId, args);
|
|
493
|
+
return invokeClientCallback(newConn, newCbId, args, options);
|
|
473
494
|
}
|
|
474
495
|
throw err;
|
|
475
496
|
}
|
|
@@ -792,6 +813,9 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
792
813
|
}
|
|
793
814
|
},
|
|
794
815
|
fetch: async (url, init) => {
|
|
816
|
+
if (init.signal.aborted) {
|
|
817
|
+
throw createAbortError();
|
|
818
|
+
}
|
|
795
819
|
const serialized = {
|
|
796
820
|
url,
|
|
797
821
|
method: init.method,
|
|
@@ -799,7 +823,16 @@ async function handleCreateRuntime(message, connection, state) {
|
|
|
799
823
|
body: init.rawBody,
|
|
800
824
|
signalAborted: init.signal.aborted
|
|
801
825
|
};
|
|
802
|
-
const
|
|
826
|
+
const callbackAbortController = new AbortController;
|
|
827
|
+
const onInitAbort = () => callbackAbortController.abort();
|
|
828
|
+
init.signal.addEventListener("abort", onInitAbort, { once: true });
|
|
829
|
+
const result = await invokeCallbackWithReconnect(callbackContext, () => callbackContext.fetch, [serialized], "Fetch", invokeClientCallback, {
|
|
830
|
+
signal: callbackAbortController.signal,
|
|
831
|
+
timeoutMs: FETCH_CALLBACK_TIMEOUT_MS,
|
|
832
|
+
timeoutLabel: "fetch callback"
|
|
833
|
+
}).finally(() => {
|
|
834
|
+
init.signal.removeEventListener("abort", onInitAbort);
|
|
835
|
+
});
|
|
803
836
|
if (result && typeof result === "object" && result.__streamingResponse) {
|
|
804
837
|
const response = result.response;
|
|
805
838
|
response.__isCallbackStream = true;
|
|
@@ -1330,6 +1363,7 @@ function handleCallbackResponse(message, connection) {
|
|
|
1330
1363
|
return;
|
|
1331
1364
|
}
|
|
1332
1365
|
connection.pendingCallbacks.delete(message.requestId);
|
|
1366
|
+
pending.cleanup?.();
|
|
1333
1367
|
if (message.error) {
|
|
1334
1368
|
const error = new Error(message.error.message);
|
|
1335
1369
|
error.name = message.error.name;
|
|
@@ -1341,12 +1375,68 @@ function handleCallbackResponse(message, connection) {
|
|
|
1341
1375
|
pending.resolve(message.result);
|
|
1342
1376
|
}
|
|
1343
1377
|
}
|
|
1344
|
-
async function invokeClientCallback(connection, callbackId, args) {
|
|
1378
|
+
async function invokeClientCallback(connection, callbackId, args, options) {
|
|
1345
1379
|
const requestId = connection.nextCallbackId++;
|
|
1380
|
+
const timeoutMs = options?.timeoutMs ?? DEFAULT_CALLBACK_TIMEOUT_MS;
|
|
1346
1381
|
return new Promise((resolve, reject) => {
|
|
1382
|
+
let settled = false;
|
|
1383
|
+
let timeoutId;
|
|
1384
|
+
let onAbort;
|
|
1385
|
+
let callbackInvokeSent = false;
|
|
1386
|
+
const settle = (handler, value) => {
|
|
1387
|
+
if (settled)
|
|
1388
|
+
return;
|
|
1389
|
+
settled = true;
|
|
1390
|
+
connection.pendingCallbacks.delete(requestId);
|
|
1391
|
+
if (timeoutId) {
|
|
1392
|
+
clearTimeout(timeoutId);
|
|
1393
|
+
timeoutId = undefined;
|
|
1394
|
+
}
|
|
1395
|
+
if (options?.signal && onAbort) {
|
|
1396
|
+
options.signal.removeEventListener("abort", onAbort);
|
|
1397
|
+
}
|
|
1398
|
+
handler(value);
|
|
1399
|
+
};
|
|
1400
|
+
onAbort = () => {
|
|
1401
|
+
if (settled)
|
|
1402
|
+
return;
|
|
1403
|
+
if (callbackInvokeSent) {
|
|
1404
|
+
sendCallbackAbortMessage(connection, requestId, options?.timeoutLabel ? `${options.timeoutLabel} aborted` : "Callback aborted");
|
|
1405
|
+
}
|
|
1406
|
+
settle(reject, createAbortError());
|
|
1407
|
+
};
|
|
1408
|
+
if (options?.signal) {
|
|
1409
|
+
if (options.signal.aborted) {
|
|
1410
|
+
onAbort();
|
|
1411
|
+
return;
|
|
1412
|
+
}
|
|
1413
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
1414
|
+
}
|
|
1415
|
+
if (timeoutMs > 0) {
|
|
1416
|
+
timeoutId = setTimeout(() => {
|
|
1417
|
+
if (settled)
|
|
1418
|
+
return;
|
|
1419
|
+
const label = options?.timeoutLabel ?? "callback";
|
|
1420
|
+
const timeoutError = new Error(`${label} timed out after ${timeoutMs}ms`);
|
|
1421
|
+
if (callbackInvokeSent) {
|
|
1422
|
+
sendCallbackAbortMessage(connection, requestId, timeoutError.message);
|
|
1423
|
+
}
|
|
1424
|
+
settle(reject, timeoutError);
|
|
1425
|
+
}, timeoutMs);
|
|
1426
|
+
}
|
|
1347
1427
|
const pending = {
|
|
1348
|
-
|
|
1349
|
-
|
|
1428
|
+
callbackId,
|
|
1429
|
+
cleanup: () => {
|
|
1430
|
+
if (timeoutId) {
|
|
1431
|
+
clearTimeout(timeoutId);
|
|
1432
|
+
timeoutId = undefined;
|
|
1433
|
+
}
|
|
1434
|
+
if (options?.signal && onAbort) {
|
|
1435
|
+
options.signal.removeEventListener("abort", onAbort);
|
|
1436
|
+
}
|
|
1437
|
+
},
|
|
1438
|
+
resolve: (result) => settle(resolve, result),
|
|
1439
|
+
reject: (error) => settle(reject, error)
|
|
1350
1440
|
};
|
|
1351
1441
|
connection.pendingCallbacks.set(requestId, pending);
|
|
1352
1442
|
const invoke = {
|
|
@@ -1356,6 +1446,7 @@ async function invokeClientCallback(connection, callbackId, args) {
|
|
|
1356
1446
|
args
|
|
1357
1447
|
};
|
|
1358
1448
|
sendMessage(connection.socket, invoke);
|
|
1449
|
+
callbackInvokeSent = true;
|
|
1359
1450
|
});
|
|
1360
1451
|
}
|
|
1361
1452
|
function handleStreamPush(message, connection) {
|
|
@@ -1480,16 +1571,36 @@ function handleCallbackStreamStart(message, connection) {
|
|
|
1480
1571
|
return Promise.resolve();
|
|
1481
1572
|
}
|
|
1482
1573
|
});
|
|
1574
|
+
const cancelStream = () => {
|
|
1575
|
+
connection.callbackStreamReceivers.delete(message.streamId);
|
|
1576
|
+
sendMessage(connection.socket, {
|
|
1577
|
+
type: import_isolate_protocol.MessageType.CALLBACK_STREAM_CANCEL,
|
|
1578
|
+
streamId: message.streamId
|
|
1579
|
+
});
|
|
1580
|
+
};
|
|
1483
1581
|
connection.callbackStreamReceivers.set(message.streamId, receiver);
|
|
1484
1582
|
const pending = connection.pendingCallbacks.get(message.requestId);
|
|
1485
|
-
if (pending) {
|
|
1486
|
-
|
|
1487
|
-
|
|
1583
|
+
if (!pending) {
|
|
1584
|
+
cancelStream();
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
try {
|
|
1588
|
+
const body = NULL_BODY_STATUSES.has(message.metadata.status) ? null : readableStream;
|
|
1589
|
+
const response = new Response(body, {
|
|
1488
1590
|
status: message.metadata.status,
|
|
1489
1591
|
statusText: message.metadata.statusText,
|
|
1490
1592
|
headers: message.metadata.headers
|
|
1491
1593
|
});
|
|
1594
|
+
connection.pendingCallbacks.delete(message.requestId);
|
|
1492
1595
|
pending.resolve({ __streamingResponse: true, response });
|
|
1596
|
+
if (body === null) {
|
|
1597
|
+
cancelStream();
|
|
1598
|
+
}
|
|
1599
|
+
} catch (err) {
|
|
1600
|
+
connection.pendingCallbacks.delete(message.requestId);
|
|
1601
|
+
cancelStream();
|
|
1602
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1603
|
+
pending.reject(error);
|
|
1493
1604
|
}
|
|
1494
1605
|
}
|
|
1495
1606
|
function handleCallbackStreamChunk(message, connection) {
|
|
@@ -1752,4 +1863,4 @@ async function handleClearCollectedData(message, connection, state) {
|
|
|
1752
1863
|
}
|
|
1753
1864
|
}
|
|
1754
1865
|
|
|
1755
|
-
//# debugId=
|
|
1866
|
+
//# debugId=8F51D70F9171DF6C64756E2164756E21
|