diff --git a/static/js/launch_progress.js b/static/js/launch_progress.js index 26fe373..276dcf4 100644 --- a/static/js/launch_progress.js +++ b/static/js/launch_progress.js @@ -1,3 +1,17 @@ +/** + * Launch Progress JavaScript + * + * This file handles the instance launch and update process, including: + * - Step-by-step progress tracking + * - Stack deployment via Portainer API + * - Error handling for HTTP 502/504 responses + * + * Note: HTTP 502 (Bad Gateway) and 504 (Gateway Timeout) errors are treated as + * potential success cases since they often occur when Portainer is busy but the + * operation may still succeed. In these cases, the system continues monitoring + * the stack status. + */ + document.addEventListener('DOMContentLoaded', function() { // Check if this is an update operation if (window.isUpdate && window.updateInstanceId && window.updateRepoId && window.updateBranch) { @@ -561,6 +575,11 @@ async function startLaunch(data) { Initiating stack deployment... +
+ + Note: Stack deployment can take several minutes. If you see HTTP 502 or 504 errors, + the deployment may still be in progress and will be monitored automatically. +
`; stackDeployStepElement.querySelector('.step-content').appendChild(stackProgressDiv); @@ -2923,6 +2942,15 @@ async function deployStack(dockerComposeContent, stackName, port) { console.log('Response status:', response.status); console.log('Response ok:', response.ok); console.log('Response headers:', Object.fromEntries(response.headers.entries())); + + // Log additional response details for debugging + if (response.status === 502) { + console.log('HTTP 502 Bad Gateway detected - this usually means Portainer is busy or slow to respond'); + console.log('The stack deployment may still be in progress despite this error'); + } else if (response.status === 504) { + console.log('HTTP 504 Gateway Timeout detected - the request took too long'); + console.log('This is expected for long-running stack deployments'); + } // Handle 504 Gateway Timeout as successful initiation if (response.status === 504) { @@ -2947,6 +2975,29 @@ async function deployStack(dockerComposeContent, stackName, port) { let errorMessage = 'Failed to deploy stack'; console.log('Response not ok, status:', response.status); + // Handle 502 Bad Gateway and 504 Gateway Timeout as potential success cases + // These errors often occur when Portainer is busy or slow to respond, but the operation may still succeed + if (response.status === 502 || response.status === 504) { + console.log(`Received HTTP ${response.status} - stack creation may still be in progress`); + console.log('HTTP 502 (Bad Gateway) typically means Portainer is busy or slow to respond'); + console.log('HTTP 504 (Gateway Timeout) means the request took too long'); + console.log('In both cases, we continue monitoring since the operation may still succeed'); + + // Update progress to show that we're now polling + const progressBar = document.getElementById('launchProgress'); + const progressText = document.getElementById('stepDescription'); + if (progressBar && progressText) { + progressBar.style.width = '25%'; + progressBar.textContent = '25%'; + progressText.textContent = `Stack creation initiated (HTTP ${response.status}, but continuing to monitor)...`; + } + + // Start polling immediately since the stack creation was initiated + console.log(`Starting to poll for stack status after HTTP ${response.status}...`); + const pollResult = await pollStackStatus(stackName, 15 * 60 * 1000); // 15 minutes max + return pollResult; + } + try { const errorData = await response.json(); errorMessage = errorData.error || errorMessage; @@ -3004,13 +3055,15 @@ async function deployStack(dockerComposeContent, stackName, port) { } catch (error) { console.error('Error deploying stack:', error); - // Check if this is a 504 timeout error that should be handled as a success + // Check if this is a 502 or 504 error that should be handled as a success if (error.message && ( error.message.includes('504 Gateway Time-out') || error.message.includes('504 Gateway Timeout') || - error.message.includes('timed out') + error.message.includes('timed out') || + error.message.includes('502') || + error.message.includes('Bad Gateway') )) { - console.log('Detected 504 timeout in catch block - treating as successful initiation'); + console.log('Detected HTTP 502/504 error in catch block - treating as successful initiation'); // Update progress to show that we're now polling const progressBar = document.getElementById('launchProgress'); @@ -3018,11 +3071,11 @@ async function deployStack(dockerComposeContent, stackName, port) { if (progressBar && progressText) { progressBar.style.width = '25%'; progressBar.textContent = '25%'; - progressText.textContent = 'Stack creation initiated (timed out, but continuing to monitor)...'; + progressText.textContent = 'Stack creation initiated (HTTP error, but continuing to monitor)...'; } // Start polling immediately since the stack creation was initiated - console.log('Starting to poll for stack status after 504 timeout from catch block...'); + console.log('Starting to poll for stack status after HTTP 502/504 error from catch block...'); const pollResult = await pollStackStatus(stackName, 15 * 60 * 1000); // 15 minutes max return pollResult; } @@ -3279,6 +3332,25 @@ async function updateStack(dockerComposeContent, stackId, port, instanceData = n let errorMessage = 'Failed to update stack'; console.log('Response not ok, status:', response.status); + // Handle 502 Bad Gateway and 504 Gateway Timeout as potential success cases + if (response.status === 502 || response.status === 504) { + console.log(`Received HTTP ${response.status} - stack update may still be in progress`); + + // Update progress to show that we're now polling + const progressBar = document.getElementById('launchProgress'); + const progressText = document.getElementById('stepDescription'); + if (progressBar && progressText) { + progressBar.style.width = '25%'; + progressBar.textContent = '25%'; + progressText.textContent = `Stack update initiated (HTTP ${response.status}, but continuing to monitor)...`; + } + + // Start polling immediately since the stack update was initiated + console.log(`Starting to poll for stack status after HTTP ${response.status}...`); + const pollResult = await pollStackStatus(stackId, 15 * 60 * 1000); // 15 minutes max + return pollResult; + } + try { const errorData = await response.json(); errorMessage = errorData.error || errorMessage; @@ -3336,13 +3408,15 @@ async function updateStack(dockerComposeContent, stackId, port, instanceData = n } catch (error) { console.error('Error updating stack:', error); - // Check if this is a 504 timeout error that should be handled as a success + // Check if this is a 502 or 504 error that should be handled as a success if (error.message && ( error.message.includes('504 Gateway Time-out') || error.message.includes('504 Gateway Timeout') || - error.message.includes('timed out') + error.message.includes('timed out') || + error.message.includes('502') || + error.message.includes('Bad Gateway') )) { - console.log('Detected 504 timeout in catch block - treating as successful initiation'); + console.log('Detected HTTP 502/504 error in catch block - treating as successful initiation'); // Update progress to show that we're now polling const progressBar = document.getElementById('launchProgress'); @@ -3350,11 +3424,11 @@ async function updateStack(dockerComposeContent, stackId, port, instanceData = n if (progressBar && progressText) { progressBar.style.width = '25%'; progressBar.textContent = '25%'; - progressText.textContent = 'Stack update initiated (timed out, but continuing to monitor)...'; + progressText.textContent = 'Stack update initiated (HTTP error, but continuing to monitor)...'; } // Start polling immediately since the stack update was initiated - console.log('Starting to poll for stack status after 504 timeout from catch block...'); + console.log('Starting to poll for stack status after HTTP 502/504 error from catch block...'); const pollResult = await pollStackStatus(stackId, 15 * 60 * 1000); // 15 minutes max return pollResult; }