Compare commits

...

5 commits

Author SHA1 Message Date
Simon Ser
afa09cfc25 lib/client: fix typo
That one turned out to be surprisingly tricky to dig out.
2024-11-12 23:11:10 +01:00
Simon Ser
977752e0f2 lib/client: bind handleOnline to this
It's used as a callback to removeEventListener().
2024-11-12 23:10:38 +01:00
Simon Ser
4bce52f162 ci: temporarily switch to alpine/edge
It has a more up-to-date nodejs version which doesn't deadlock in
"npm install".
2024-11-12 23:10:34 +01:00
Simon Ser
75ec7cd212 lib/client: don't throttle reconnections if opened long ago
If a connection was opened a long time ago, and recently got broken,
try to reconnect immediately.
2024-11-12 23:10:30 +01:00
Simon Ser
24e6767cab client: reconnect immediately if network comes online during backoff 2024-11-12 23:10:22 +01:00
2 changed files with 25 additions and 10 deletions

View file

@ -1,4 +1,5 @@
image: alpine/latest
# TODO switch back to alpine/latest once the "npm install" deadlock is fixed
image: alpine/edge
packages:
- npm
- rsync

View file

@ -74,8 +74,8 @@ class IRCError extends Error {
class Backoff {
n = 0;
constructor(min, max) {
this.min = min;
constructor(base, max) {
this.base = base;
this.max = max;
}
@ -86,10 +86,10 @@ class Backoff {
next() {
if (this.n === 0) {
this.n = 1;
return this.min;
return 0;
}
let dur = this.n * this.min;
let dur = this.n * this.base;
if (dur > this.max) {
dur = this.max;
} else {
@ -134,6 +134,7 @@ export default class Client extends EventTarget {
autoReconnect = true;
reconnectTimeoutID = null;
reconnectBackoff = new Backoff(RECONNECT_MIN_DELAY_MSEC, RECONNECT_MAX_DELAY_MSEC);
lastReconnectDate = new Date(0);
pingIntervalID = null;
pendingCmds = {
WHO: Promise.resolve(null),
@ -147,6 +148,8 @@ export default class Client extends EventTarget {
constructor(params) {
super();
this.handleOnline = this.handleOnline.bind(this);
this.params = { ...this.params, ...params };
this.reconnect();
@ -159,6 +162,7 @@ export default class Client extends EventTarget {
console.log("Connecting to " + this.params.url);
this.setStatus(Client.Status.CONNECTING);
this.lastReconnectDate = new Date();
try {
this.ws = new WebSocket(this.params.url);
@ -201,15 +205,16 @@ export default class Client extends EventTarget {
this.monitored = new irc.CaseMapMap(null, irc.CaseMapping.RFC1459);
if (this.autoReconnect) {
window.addEventListener("online", this.handleOnline);
if (!navigator.onLine) {
console.info("Waiting for network to go back online");
const handleOnline = () => {
window.removeEventListener("online", handleOnline);
this.reconnect();
};
window.addEventListener("online", handleOnline);
} else {
let delay = this.reconnectBackoff.next();
let sinceLastReconnect = new Date().getTime() - this.lastReconnectDate.getTime();
if (sinceLastReconnect < RECONNECT_MIN_DELAY_MSEC) {
delay = Math.max(delay, RECONNECT_MIN_DELAY_MSEC);
}
console.info("Reconnecting to server in " + (delay / 1000) + " seconds");
clearTimeout(this.reconnectTimeoutID);
this.reconnectTimeoutID = setTimeout(() => {
@ -226,6 +231,8 @@ export default class Client extends EventTarget {
clearTimeout(this.reconnectTimeoutID);
this.reconnectTimeoutID = null;
window.removeEventListener("online", this.handleOnline);
this.setPingInterval(0);
if (this.ws) {
@ -245,6 +252,13 @@ export default class Client extends EventTarget {
this.dispatchEvent(new CustomEvent("error", { detail: err }));
}
handleOnline() {
window.removeEventListener("online", this.handleOnline);
if (this.autoReconnect && this.status === Client.Status.DISCONNECTED) {
this.reconnect();
}
}
handleOpen() {
console.log("Connection opened");
this.setStatus(Client.Status.REGISTERING);