Serialize refresh scheduling and remove overlap polling
This commit is contained in:
@@ -30,8 +30,55 @@ import {
|
||||
refreshPhaseData,
|
||||
} from "./js/data.js";
|
||||
initI18n();
|
||||
|
||||
const REFRESH_INTERVAL_MS = 4000;
|
||||
let refreshInFlight = null;
|
||||
let refreshTimerId = null;
|
||||
let refreshSchedulerStarted = false;
|
||||
|
||||
async function runSerializedRefresh() {
|
||||
if (refreshInFlight) return refreshInFlight;
|
||||
refreshInFlight = refreshPhaseData().finally(() => {
|
||||
refreshInFlight = null;
|
||||
});
|
||||
return refreshInFlight;
|
||||
}
|
||||
|
||||
async function refreshWithUiErrorHandling() {
|
||||
try {
|
||||
await runSerializedRefresh();
|
||||
} catch (err) {
|
||||
if (!handleAuthError(err, clearUserState)) toast(err.message, true);
|
||||
}
|
||||
}
|
||||
|
||||
function scheduleNextRefresh() {
|
||||
refreshTimerId = window.setTimeout(async () => {
|
||||
if (!document.hidden) {
|
||||
await refreshWithUiErrorHandling();
|
||||
}
|
||||
scheduleNextRefresh();
|
||||
}, REFRESH_INTERVAL_MS);
|
||||
}
|
||||
|
||||
function startRefreshScheduler() {
|
||||
if (refreshSchedulerStarted) return;
|
||||
refreshSchedulerStarted = true;
|
||||
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
if (!document.hidden) {
|
||||
refreshWithUiErrorHandling();
|
||||
}
|
||||
});
|
||||
|
||||
if (refreshTimerId !== null) {
|
||||
window.clearTimeout(refreshTimerId);
|
||||
}
|
||||
scheduleNextRefresh();
|
||||
}
|
||||
|
||||
configureUiRuntime({
|
||||
refreshPhaseData,
|
||||
refreshPhaseData: runSerializedRefresh,
|
||||
loadSuggestData,
|
||||
loadVoteData,
|
||||
handleAuthError: (err) => handleAuthError(err, clearUserState),
|
||||
@@ -105,7 +152,7 @@ function setupHandlers() {
|
||||
setSavedUsername(username);
|
||||
state.isAuthenticated = true;
|
||||
setAuthUI(true);
|
||||
await refreshPhaseData();
|
||||
await runSerializedRefresh();
|
||||
toast(t("toast.loggedIn"));
|
||||
} catch (err) {
|
||||
if (err?.status === 401) return toast(t("auth.invalidCredentials"), true);
|
||||
@@ -132,7 +179,7 @@ function setupHandlers() {
|
||||
setSavedUsername(username);
|
||||
state.isAuthenticated = true;
|
||||
setAuthUI(true);
|
||||
await refreshPhaseData();
|
||||
await runSerializedRefresh();
|
||||
toast(t("toast.registered"));
|
||||
} catch (err) {
|
||||
if (handleAuthError(err, clearUserState)) return;
|
||||
@@ -214,7 +261,7 @@ function setupHandlers() {
|
||||
}
|
||||
renderPhasePill();
|
||||
toast(t("admin.resultsUpdated"));
|
||||
await refreshPhaseData();
|
||||
await runSerializedRefresh();
|
||||
} catch (err) {
|
||||
e.target.checked = !desired;
|
||||
toast(err.message, true);
|
||||
@@ -233,7 +280,7 @@ function setupHandlers() {
|
||||
try {
|
||||
await adminApi.linkSuggestions(source, target);
|
||||
toast(t("admin.linkDone"));
|
||||
await refreshPhaseData();
|
||||
await runSerializedRefresh();
|
||||
} catch (err) {
|
||||
toast(err.message, true);
|
||||
}
|
||||
@@ -250,7 +297,7 @@ function setupHandlers() {
|
||||
try {
|
||||
await adminApi.grantJoker(playerId);
|
||||
toast(t("admin.jokerGranted"));
|
||||
await refreshPhaseData();
|
||||
await runSerializedRefresh();
|
||||
} catch (err) {
|
||||
toast(err.message, true);
|
||||
}
|
||||
@@ -266,7 +313,7 @@ function setupHandlers() {
|
||||
await adminApi.deletePlayer(playerId);
|
||||
toast(t("admin.deleteDone"));
|
||||
close();
|
||||
await refreshPhaseData();
|
||||
await runSerializedRefresh();
|
||||
} catch (err) {
|
||||
toast(err.message, true);
|
||||
}
|
||||
@@ -281,7 +328,7 @@ async function adminAction(fn, successMessage) {
|
||||
try {
|
||||
await fn();
|
||||
toast(successMessage);
|
||||
await refreshPhaseData();
|
||||
await runSerializedRefresh();
|
||||
} catch (err) {
|
||||
toast(err.message, true);
|
||||
}
|
||||
@@ -289,16 +336,8 @@ async function adminAction(fn, successMessage) {
|
||||
|
||||
async function main() {
|
||||
setupHandlers();
|
||||
try {
|
||||
await refreshPhaseData();
|
||||
} catch (err) {
|
||||
toast(err.message, true);
|
||||
}
|
||||
setInterval(() => {
|
||||
refreshPhaseData().catch((err) => {
|
||||
if (!handleAuthError(err, clearUserState)) toast(err.message, true);
|
||||
});
|
||||
}, 4000);
|
||||
await refreshWithUiErrorHandling();
|
||||
startRefreshScheduler();
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -358,7 +397,7 @@ function bindNavButtons() {
|
||||
state.resultsOpen = resp.resultsOpen ?? state.resultsOpen;
|
||||
state.votesRendered = false;
|
||||
renderPhasePill();
|
||||
await refreshPhaseData();
|
||||
await runSerializedRefresh();
|
||||
} catch (err) {
|
||||
toast(err.message, true);
|
||||
}
|
||||
@@ -376,7 +415,7 @@ function bindNavButtons() {
|
||||
state.resultsOpen = resp.resultsOpen ?? state.resultsOpen;
|
||||
state.votesRendered = false;
|
||||
renderPhasePill();
|
||||
await refreshPhaseData();
|
||||
await runSerializedRefresh();
|
||||
} catch (err) {
|
||||
toast(err.message, true);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user