From 9cd9e84be6eb1176bc64bc2e32680209c02f36e1 Mon Sep 17 00:00:00 2001 From: Nicolas Dorier Date: Wed, 27 Sep 2023 16:05:57 +0900 Subject: [PATCH] Fix: After a while, a busy server would send error HTTP 500 (#5354) This was due to Blazor which attempt to reconnect when the connection is broken. Before this, it would try again indefinitely, with this PR, it tries only for around 3 minutes. After this, the Blazor circuit should be dead anyway, so it's useless to try again. --- BTCPayServer/wwwroot/main/site.js | 48 ++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/BTCPayServer/wwwroot/main/site.js b/BTCPayServer/wwwroot/main/site.js index a24167591..533010926 100644 --- a/BTCPayServer/wwwroot/main/site.js +++ b/BTCPayServer/wwwroot/main/site.js @@ -342,58 +342,72 @@ document.addEventListener("DOMContentLoaded", () => { if (window.Blazor) { let isUnloading = false; window.addEventListener("beforeunload", () => { isUnloading = true; }); + let brokenConnection = { + isConnected: false, + titleContent: 'Connection broken', + innerHTML: 'Please refresh the page.' + }; + let interruptedConnection = { + isConnected: false, + titleContent: 'Connection interrupted', + innerHTML: 'Attempt to reestablish the connection in a few seconds...' + }; + let successfulConnection = { + isConnected: true, + titleContent: 'Connection established', + innerHTML: '' // use empty link on purpose + }; class BlazorReconnectionHandler { reconnecting = false; async onConnectionDown(options, _error) { if (this.reconnecting) return; - this.setBlazorStatus(false); + this.setBlazorStatus(interruptedConnection); this.reconnecting = true; console.debug('Blazor hub connection lost'); await this.reconnect(); } + async reconnect() { - let delays = [500, 1000, 2000, 4000, 8000, 16000, 20000]; + let delays = [500, 1000, 2000, 4000, 8000, 16000, 20000, 40000]; let i = 0; const lastDelay = delays.length - 1; - while (true) { + while (i < delays.length) { await this.delay(delays[i]); try { if (await Blazor.reconnect()) - break; - - this.setBlazorStatus(false); + return; console.warn('Error while reconnecting to Blazor hub (Broken circuit)'); + break; } catch (err) { - this.setBlazorStatus(false); + this.setBlazorStatus(interruptedConnection); console.warn(`Error while reconnecting to Blazor hub (${err})`); } i++; - if (i > lastDelay) - i = lastDelay; } + this.setBlazorStatus(brokenConnection); } onConnectionUp() { this.reconnecting = false; console.debug('Blazor hub connected'); - this.setBlazorStatus(true); + this.setBlazorStatus(successfulConnection); } - setBlazorStatus(isConnected) { + setBlazorStatus(content) { document.querySelectorAll('.blazor-status').forEach($status => { const $state = $status.querySelector('.blazor-status__state'); const $title = $status.querySelector('.blazor-status__title'); const $body = $status.querySelector('.blazor-status__body'); $state.classList.remove('btcpay-status--enabled'); $state.classList.remove('btcpay-status--disabled'); - $state.classList.add('btcpay-status--' + (isConnected ? 'enabled' : 'disabled')); - $title.textContent = isConnected ? 'Connection established' : 'Connection interrupted'; - $body.innerHTML = isConnected ? '' : 'Please refresh the page.'; // use empty link on purpose - $body.classList.toggle('d-none', isConnected); + $state.classList.add(content.isConnected ? 'btcpay-status--enabled' : 'btcpay-status--disabled'); + $title.textContent = content.titleContent; + $body.innerHTML = content.innerHTML; + $body.classList.toggle('d-none', content.isConnected); if (!isUnloading) { const toast = new bootstrap.Toast($status, { autohide: false }); - if (isConnected) { + if (content.isConnected) { if (toast.isShown()) toast.hide(); } @@ -410,7 +424,7 @@ if (window.Blazor) { } const handler = new BlazorReconnectionHandler(); - handler.setBlazorStatus(true); + handler.setBlazorStatus(successfulConnection); Blazor.start({ reconnectionHandler: handler });