From 0bbdf0eaab1633b7f6f69ebc1c0dfaf044da7122 Mon Sep 17 00:00:00 2001 From: Kobe Date: Mon, 23 Jun 2025 09:35:15 +0200 Subject: [PATCH] better timeouts --- routes/__pycache__/main.cpython-313.pyc | Bin 104187 -> 104187 bytes routes/main.py | 6 +- static/js/launch_progress.js | 144 +++++++++++++++--------- 3 files changed, 96 insertions(+), 54 deletions(-) diff --git a/routes/__pycache__/main.cpython-313.pyc b/routes/__pycache__/main.cpython-313.pyc index 77fedddc3965b3dd3de0d09b2e4b4c077bab2e25..4ededb4c6a5d74464df0e89f4d3f1eec6731fcf4 100644 GIT binary patch delta 71 zcmeypmhJaiHr~&?yj%=GP|O^e(YBFybqZtQ=A9`ej4VtS#jQ6RroCnd3drW^v9JhT Z6t|h|Uv!Nn?4nY5vu5#j&0@w&$^dGh7 -
-
Instance Information
-
- - - - - - - - - - - - - - - - - -
PropertyValue
Internal Port${data.port}
Domains${data.webAddresses.join(', ')}
-
-
- - `; - saveDataStep.querySelector('.step-content').appendChild(instanceDetails); - // After saving instance data, add the health check step await updateStep(11, 'Health Check', 'Verifying instance health...'); + + // Add a progress indicator + const healthStepElement = document.querySelectorAll('.step-item')[10]; + const progressDiv = document.createElement('div'); + progressDiv.className = 'mt-2'; + progressDiv.innerHTML = ` +
+
+ 0% +
+
+ Starting health check... + `; + healthStepElement.querySelector('.step-content').appendChild(progressDiv); + const healthResult = await checkInstanceHealth(`https://${data.webAddresses[0]}`); if (!healthResult.success) { @@ -612,7 +598,7 @@ async function startLaunch(data) { } // Add a retry button if health check fails - const healthStep = document.querySelectorAll('.step-item')[10]; + const healthStepElement2 = document.querySelectorAll('.step-item')[10]; if (!healthResult.success) { const retryButton = document.createElement('button'); retryButton.className = 'btn btn-sm btn-warning mt-2'; @@ -622,15 +608,15 @@ async function startLaunch(data) { retryButton.innerHTML = ' Checking...'; const retryResult = await checkInstanceHealth(`https://${data.webAddresses[0]}`); if (retryResult.success) { - healthStep.classList.remove('failed'); - healthStep.classList.add('completed'); + healthStepElement2.classList.remove('failed'); + healthStepElement2.classList.add('completed'); retryButton.remove(); } else { retryButton.disabled = false; retryButton.innerHTML = ' Retry Health Check'; } }; - healthStep.querySelector('.step-content').appendChild(retryButton); + healthStepElement2.querySelector('.step-content').appendChild(retryButton); } // After health check, add authentication step @@ -2242,11 +2228,19 @@ async function saveInstanceData(instanceData) { } async function checkInstanceHealth(instanceUrl) { - const maxRetries = 5; + const maxRetries = 120; // 120 retries * 5 seconds = 10 minutes total + const baseDelay = 5000; // 5 seconds base delay let currentAttempt = 1; + const startTime = Date.now(); + const maxTotalTime = 10 * 60 * 1000; // 10 minutes in milliseconds while (currentAttempt <= maxRetries) { try { + // Check if we've exceeded the total timeout + if (Date.now() - startTime > maxTotalTime) { + throw new Error('Health check timeout: 10 minutes exceeded'); + } + // First get the instance ID from the database const response = await fetch('/instances'); const text = await response.text(); @@ -2280,16 +2274,31 @@ async function checkInstanceHealth(instanceUrl) { const data = await statusResponse.json(); // Update the health check step - const healthStep = document.querySelectorAll('.step-item')[8]; // Adjust index based on your steps - healthStep.classList.remove('active'); - healthStep.classList.add('completed'); - const statusText = healthStep.querySelector('.step-status'); + const healthStepElement = document.querySelectorAll('.step-item')[10]; // Adjust index based on your steps + healthStepElement.classList.remove('active'); + healthStepElement.classList.add('completed'); + const statusText = healthStepElement.querySelector('.step-status'); if (data.status === 'active') { - statusText.textContent = `Instance is healthy (Attempt ${currentAttempt}/${maxRetries})`; + const elapsedTime = Math.round((Date.now() - startTime) / 1000); + statusText.textContent = `Instance is healthy (Attempt ${currentAttempt}/${maxRetries}, ${elapsedTime}s elapsed)`; + + // Update progress bar to 100% + const progressBar = document.getElementById('healthProgress'); + const progressText = document.getElementById('healthProgressText'); + if (progressBar && progressText) { + progressBar.style.width = '100%'; + progressBar.textContent = '100%'; + progressBar.classList.remove('progress-bar-animated'); + progressBar.classList.add('bg-success'); + progressText.textContent = `Health check completed successfully in ${elapsedTime}s`; + } + return { success: true, - data: data + data: data, + attempts: currentAttempt, + elapsedTime: elapsedTime }; } else { throw new Error('Instance is not healthy'); @@ -2297,25 +2306,58 @@ async function checkInstanceHealth(instanceUrl) { } catch (error) { console.error(`Health check attempt ${currentAttempt} failed:`, error); - // Update status to show current attempt - const healthStep = document.querySelectorAll('.step-item')[8]; - const statusText = healthStep.querySelector('.step-status'); - statusText.textContent = `Health check failed (Attempt ${currentAttempt}/${maxRetries}): ${error.message}`; + // Update status to show current attempt and elapsed time + const healthStepElement = document.querySelectorAll('.step-item')[10]; + const statusText = healthStepElement.querySelector('.step-status'); + const elapsedTime = Math.round((Date.now() - startTime) / 1000); + statusText.textContent = `Health check failed (Attempt ${currentAttempt}/${maxRetries}, ${elapsedTime}s elapsed): ${error.message}`; - if (currentAttempt === maxRetries) { + // Update progress bar + const progressBar = document.getElementById('healthProgress'); + const progressText = document.getElementById('healthProgressText'); + if (progressBar && progressText) { + const progressPercent = Math.min((currentAttempt / maxRetries) * 100, 100); + progressBar.style.width = `${progressPercent}%`; + progressBar.textContent = `${Math.round(progressPercent)}%`; + progressText.textContent = `Attempt ${currentAttempt}/${maxRetries} (${elapsedTime}s elapsed)`; + } + + if (currentAttempt === maxRetries || (Date.now() - startTime > maxTotalTime)) { + // Update progress bar to show failure + if (progressBar && progressText) { + progressBar.classList.remove('progress-bar-animated'); + progressBar.classList.add('bg-danger'); + progressText.textContent = `Health check failed after ${currentAttempt} attempts (${elapsedTime}s)`; + } + return { success: false, - error: `Health check failed after ${maxRetries} attempts: ${error.message}` + error: `Health check failed after ${currentAttempt} attempts (${elapsedTime}s): ${error.message}` }; } - // Wait 5 seconds before next attempt - await new Promise(resolve => setTimeout(resolve, 5000)); + // Wait before next attempt (5 seconds base delay) + await new Promise(resolve => setTimeout(resolve, baseDelay)); currentAttempt++; + + // Update progress bar in real-time + updateHealthProgress(currentAttempt, maxRetries, elapsedTime); } } } +function updateHealthProgress(currentAttempt, maxRetries, elapsedTime) { + const progressBar = document.getElementById('healthProgress'); + const progressText = document.getElementById('healthProgressText'); + + if (progressBar && progressText) { + const progressPercent = Math.min((currentAttempt / maxRetries) * 100, 100); + progressBar.style.width = `${progressPercent}%`; + progressBar.textContent = `${Math.round(progressPercent)}%`; + progressText.textContent = `Attempt ${currentAttempt}/${maxRetries} (${elapsedTime}s elapsed)`; + } +} + async function authenticateInstance(instanceUrl, instanceId) { try { // First check if instance is already authenticated