@shipers-dev/multi 0.10.0 → 0.10.1
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/index.js +28 -20
- package/package.json +1 -1
- package/src/index.ts +28 -18
package/dist/index.js
CHANGED
|
@@ -5703,7 +5703,7 @@ import { join as join3, dirname as dirname2 } from "path";
|
|
|
5703
5703
|
// package.json
|
|
5704
5704
|
var package_default = {
|
|
5705
5705
|
name: "@shipers-dev/multi",
|
|
5706
|
-
version: "0.10.
|
|
5706
|
+
version: "0.10.1",
|
|
5707
5707
|
type: "module",
|
|
5708
5708
|
bin: {
|
|
5709
5709
|
"multi-agent": "./dist/index.js"
|
|
@@ -6194,30 +6194,38 @@ async function cmdConnect(apiUrl, config) {
|
|
|
6194
6194
|
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
6195
6195
|
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
6196
6196
|
schedule();
|
|
6197
|
+
let restarting = false;
|
|
6197
6198
|
const restartTunnel = async (reason) => {
|
|
6198
|
-
if (!alive)
|
|
6199
|
+
if (!alive || restarting)
|
|
6199
6200
|
return;
|
|
6200
|
-
|
|
6201
|
+
restarting = true;
|
|
6201
6202
|
try {
|
|
6202
|
-
tunnel
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6203
|
+
log(`\uD83D\uDD01 Restarting tunnel (${reason})`);
|
|
6204
|
+
const old = tunnel;
|
|
6205
|
+
tunnel = null;
|
|
6206
|
+
try {
|
|
6207
|
+
old?.child.kill();
|
|
6208
|
+
} catch {}
|
|
6209
|
+
for (let attempt = 1;alive; attempt++) {
|
|
6210
|
+
const next = await startTunnel(port);
|
|
6211
|
+
if (next) {
|
|
6212
|
+
tunnel = next;
|
|
6213
|
+
log(`\u2601\uFE0F Tunnel up: ${tunnel.url}`);
|
|
6214
|
+
try {
|
|
6215
|
+
const pending = await heartbeat();
|
|
6216
|
+
if (pending > 0)
|
|
6217
|
+
drainOfflineDispatches(apiUrl, config.deviceId, config.dispatchSecret, db, () => schedule());
|
|
6218
|
+
} catch (e) {
|
|
6219
|
+
log(`heartbeat error after tunnel restart: ${String(e)}`);
|
|
6220
|
+
}
|
|
6221
|
+
return;
|
|
6215
6222
|
}
|
|
6216
|
-
|
|
6223
|
+
const wait = Math.min(30000, 2000 * attempt);
|
|
6224
|
+
log(`tunnel restart failed, retry in ${wait}ms`);
|
|
6225
|
+
await sleep(wait);
|
|
6217
6226
|
}
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
await sleep(wait);
|
|
6227
|
+
} finally {
|
|
6228
|
+
restarting = false;
|
|
6221
6229
|
}
|
|
6222
6230
|
};
|
|
6223
6231
|
(async () => {
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -481,27 +481,36 @@ async function cmdConnect(apiUrl: string, config: Config) {
|
|
|
481
481
|
schedule();
|
|
482
482
|
|
|
483
483
|
// Tunnel self-heal: relaunch cloudflared if child exits or DNS stops resolving.
|
|
484
|
+
// `restarting` guards against two entries racing (probe-failure + exit-watcher
|
|
485
|
+
// both firing when we kill the child as part of our own restart).
|
|
486
|
+
let restarting = false;
|
|
484
487
|
const restartTunnel = async (reason: string) => {
|
|
485
|
-
if (!alive) return;
|
|
486
|
-
|
|
487
|
-
try {
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
488
|
+
if (!alive || restarting) return;
|
|
489
|
+
restarting = true;
|
|
490
|
+
try {
|
|
491
|
+
log(`🔁 Restarting tunnel (${reason})`);
|
|
492
|
+
const old = tunnel;
|
|
493
|
+
tunnel = null; // null first so the exit-watcher's `tunnel === t` check skips our own kill
|
|
494
|
+
try { old?.child.kill(); } catch {}
|
|
495
|
+
for (let attempt = 1; alive; attempt++) {
|
|
496
|
+
const next = await startTunnel(port);
|
|
497
|
+
if (next) {
|
|
498
|
+
tunnel = next;
|
|
499
|
+
log(`☁️ Tunnel up: ${tunnel.url}`);
|
|
500
|
+
try {
|
|
501
|
+
const pending = await heartbeat();
|
|
502
|
+
if (pending > 0) void drainOfflineDispatches(apiUrl, config.deviceId!, config.dispatchSecret!, db, () => schedule());
|
|
503
|
+
} catch (e) {
|
|
504
|
+
log(`heartbeat error after tunnel restart: ${String(e)}`);
|
|
505
|
+
}
|
|
506
|
+
return;
|
|
499
507
|
}
|
|
500
|
-
|
|
508
|
+
const wait = Math.min(30000, 2000 * attempt);
|
|
509
|
+
log(`tunnel restart failed, retry in ${wait}ms`);
|
|
510
|
+
await sleep(wait);
|
|
501
511
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
await sleep(wait);
|
|
512
|
+
} finally {
|
|
513
|
+
restarting = false;
|
|
505
514
|
}
|
|
506
515
|
};
|
|
507
516
|
|
|
@@ -512,6 +521,7 @@ async function cmdConnect(apiUrl: string, config: Config) {
|
|
|
512
521
|
if (!t) { await sleep(1000); continue; }
|
|
513
522
|
const code = await t.child.exited;
|
|
514
523
|
if (!alive) return;
|
|
524
|
+
// If `tunnel` was nulled by restartTunnel, we killed it ourselves — skip.
|
|
515
525
|
if (tunnel === t) await restartTunnel(`cloudflared exited code=${code}`);
|
|
516
526
|
}
|
|
517
527
|
})();
|