From cd036edbac56cee8b367a3b2fbbfbbb18c3d3fde Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Wed, 10 Jul 2024 10:42:53 +0200 Subject: statusbot: .well-known retry mechanism --- modules/statusbot/statusbot.js | 65 +++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 14 deletions(-) (limited to 'modules/statusbot/statusbot.js') diff --git a/modules/statusbot/statusbot.js b/modules/statusbot/statusbot.js index da81d82..1af5804 100644 --- a/modules/statusbot/statusbot.js +++ b/modules/statusbot/statusbot.js @@ -110,6 +110,36 @@ class PRatelimit { } } +// f: ((true, ...Args) => () | (false) => ()) => () +// cb: (true, ...Args) => () | (false) => () +// The callback to f should be invoked with 'true' plus further arguments if it +// succeeded, and 'false' if it did not. +// Based on this info, if f failed, f is retried a few times. Once ntimes has +// been exhausted or a call succeeds, cb is invoked with respectively either +// (false) or (true, ...args). +function pretry(interval, multiplier, ntimes, f, cb) { + let tm = interval; + let ncalled = 0; + + function schedule() { + setTimeout(() => { + f((success, ...args) => { + if (success) { + cb(true, ...args); + return; + } + + ncalled++; + tm *= multiplier; + if (ncalled >= ntimes) cb(false); + else schedule(); + }); + }, tm); + } + + schedule(); +} + // cb: (state) => () function augmentConfig(config, cb) { const m = config.user_id.match(/^@[^:]+:(.*)$/); @@ -126,20 +156,27 @@ function augmentConfig(config, cb) { } // wait a bit with requesting this in case the homeserver in question is the same server as us - setTimeout(() => { - fetch("GET", {}, home_server, "/.well-known/matrix/server", "", (status, body) => { - if (status != 200) { - throw new Error(`statusbot: Failed getting https://${home_server}/.well-known/matrix/server`); - } - const mserver = JSON.parse(body)["m.server"]; - const m = mserver.match(/^([^:]*)(:443)?$/); - if (!m) { - throw new Error(`statusbot: Matrix server port not 443 (sorry): <${mserver}>`); - } - const matrix_server = m[1]; - cb({config, home_server, matrix_server, access_token, req_counter}); - }); - }, 100); + pretry(500, 1.2, 10, + cb => { + fetch("GET", {}, home_server, "/.well-known/matrix/server", "", (status, body) => { + if (status != 200) { + cb(false); // attempt failed (perhaps a later attempt will succeed) + } + const mserver = JSON.parse(body)["m.server"]; + const m = mserver.match(/^([^:]*)(:443)?$/); + if (!m) { + throw new Error(`statusbot: Matrix server port not 443 (sorry): <${mserver}>`); + } + const matrix_server = m[1]; + // attempt succeeded! + cb(true, {config, home_server, matrix_server, access_token, req_counter}); + }); + }, + (success, state) => { + if (success) cb(state); + else throw new Error(`statusbot: Failed getting https://${home_server}/.well-known/matrix/server`); + } + ); } function updatePersist() { -- cgit v1.2.3-70-g09d2