@mikkel-ol/tunnelmole
Version:
Tunnelmole, an open source ngrok alternative. Instant public URLs for any http/https based application. Available as a command line application or as an NPM dependency for your code. Stable and maintained. Good test coverage. Works behind firewalls
64 lines (54 loc) • 1.9 kB
text/typescript
/*
* Handle automatic reconnection if a custom subdomain is used. Use a delay with exponential backoff.
*/
import log from "../logging/log.js";
import { Options } from "../options.js";
import { connect } from "./connect.js";
import HostipWebSocket from "./host-ip-websocket";
let reconnectAttempts = 0;
let isReconnecting = false;
const maxReconnectDelay = 30000; // Maximum delay of 30 seconds
const baseReconnectDelay = 1000; // Start with 1 second
// Every 6 hours, reset reconnectAttempts. This should keep reconnections fast for long lived connections.
let resetConnnectionAttemptsInterval;
const resetTheConnectionAttemptsInterval = () => {
resetConnnectionAttemptsInterval = setInterval(() => {
reconnectAttempts = 0;
}, 21600000);
};
const attemptReconnection = async (options: Options) => {
if (isReconnecting) return;
isReconnecting = true;
reconnectAttempts++;
const reconnectDelay = Math.min(
baseReconnectDelay * Math.pow(2, reconnectAttempts - 1),
maxReconnectDelay,
);
setTimeout(async () => {
log("Got disconnected, attempting to reconnect...", "warning");
try {
const newWebsocket = await connect(options);
isReconnecting = false;
setUpAutoReconnect(options, newWebsocket);
} catch (error) {
log("Reconnection attempt failed.", "error");
isReconnecting = false;
attemptReconnection(options);
}
}, reconnectDelay);
};
const setUpAutoReconnect = async (
options: Options,
websocket: HostipWebSocket,
) => {
// We can only reliably reconnect custom subdomains. Otherwise you'd get another random subdomain on reconnection
if (typeof options.domain !== "string") {
return;
}
// Set up the websocket connection to auto reconnect
websocket.on("close", () => {
attemptReconnection(options);
});
resetTheConnectionAttemptsInterval();
};
export { setUpAutoReconnect };