Files
notifications-admin/app/assets/javascripts/socketio.js

133 lines
3.3 KiB
JavaScript
Raw Normal View History

2025-04-18 11:45:18 -07:00
document.addEventListener('DOMContentLoaded', function () {
const isJobPage = window.location.pathname.includes('/jobs/');
2025-04-09 16:57:42 -07:00
if (!isJobPage) return;
2025-04-18 11:45:18 -07:00
const jobEl = document.querySelector('[data-job-id]');
2025-04-10 12:35:04 -07:00
const jobId = jobEl?.dataset?.jobId;
2025-04-18 11:45:18 -07:00
const featureEnabled = jobEl?.dataset?.feature === 'true';
2025-04-21 15:56:19 -07:00
const apiHost = jobEl?.dataset?.host;
2025-04-10 12:35:04 -07:00
if (!jobId || !featureEnabled) return;
2025-05-22 12:03:18 -07:00
const DEFAULT_INTERVAL_MS = 10000;
const MIN_INTERVAL_MS = 1000;
const MAX_INTERVAL_MS = 30000;
2025-05-22 12:03:18 -07:00
let pollInterval;
let currentInterval = DEFAULT_INTERVAL_MS;
let isPolling = false;
2025-04-09 16:57:42 -07:00
function calculateBackoff(responseTime) {
return Math.min(
MAX_INTERVAL_MS,
Math.max(
MIN_INTERVAL_MS,
Math.floor((250 * Math.sqrt(responseTime)) - 1000)
)
);
}
2025-09-22 11:09:51 -07:00
async function updateAllJobSections(retryCount = 0) {
2025-09-17 10:00:29 -07:00
if (isPolling || document.hidden) {
return;
}
2025-03-27 14:27:43 -07:00
isPolling = true;
const startTime = Date.now();
2025-04-09 16:57:42 -07:00
const resourceEl = document.querySelector('[data-socket-update="status"]');
const url = resourceEl?.dataset?.resource;
if (!url) {
isPolling = false;
2025-04-09 16:57:42 -07:00
return;
}
try {
const response = await fetch(url);
2025-09-17 10:00:29 -07:00
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
const sections = {
status: document.querySelector('[data-socket-update="status"]'),
counts: document.querySelector('[data-socket-update="counts"]'),
notifications: document.querySelector('[data-socket-update="notifications"]'),
};
if (data.status && sections.status) {
sections.status.innerHTML = data.status;
}
if (data.counts && sections.counts) {
sections.counts.innerHTML = data.counts;
}
if (data.notifications && sections.notifications) {
sections.notifications.innerHTML = data.notifications;
}
const responseTime = Date.now() - startTime;
currentInterval = calculateBackoff(responseTime);
2025-09-22 12:13:15 -07:00
if (data.finished === true) {
stopPolling();
}
} catch (error) {
2025-09-22 11:09:51 -07:00
if (retryCount < 3) {
console.debug(`Job polling retry ${retryCount}`, error.message);
isPolling = false;
const retryDelay = Math.pow(2, retryCount) * 1000;
setTimeout(() => {
updateAllJobSections(retryCount + 1);
}, retryDelay);
return;
}
console.warn('Job polling failed after 3 retries:', {
2025-09-17 10:00:29 -07:00
error: error.message,
url: url,
jobId: jobId,
timestamp: new Date().toISOString()
});
currentInterval = Math.min(currentInterval * 2, MAX_INTERVAL_MS);
} finally {
isPolling = false;
}
2025-04-09 16:57:42 -07:00
}
function startPolling() {
updateAllJobSections();
function scheduleNext() {
if (pollInterval) clearTimeout(pollInterval);
pollInterval = setTimeout(() => {
updateAllJobSections();
scheduleNext();
}, currentInterval);
}
scheduleNext();
}
function stopPolling() {
if (pollInterval) {
clearTimeout(pollInterval);
pollInterval = null;
}
}
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
stopPolling();
} else {
startPolling();
}
});
window.addEventListener('beforeunload', stopPolling);
startPolling();
2025-04-09 16:57:42 -07:00
});