diff --git a/routes/__pycache__/main.cpython-313.pyc b/routes/__pycache__/main.cpython-313.pyc
index 77feddd..4ededb4 100644
Binary files a/routes/__pycache__/main.cpython-313.pyc and b/routes/__pycache__/main.cpython-313.pyc differ
diff --git a/routes/main.py b/routes/main.py
index ba0562f..00b7168 100644
--- a/routes/main.py
+++ b/routes/main.py
@@ -350,7 +350,7 @@ def init_routes(main_bp):
try:
# Construct the health check URL
health_url = f"{instance.main_url.rstrip('/')}/health"
- response = requests.get(health_url, timeout=5)
+ response = requests.get(health_url, timeout=30) # Increased timeout to 30 seconds
if response.status_code == 200:
data = response.json()
@@ -397,7 +397,7 @@ def init_routes(main_bp):
deployed_commit = None
try:
version_url = f"{instance.main_url.rstrip('/')}/api/version"
- resp = requests.get(version_url, timeout=5)
+ resp = requests.get(version_url, timeout=30) # Increased timeout to 30 seconds
if resp.status_code == 200:
version_data = resp.json()
deployed_version = version_data.get('version', 'unknown')
@@ -419,7 +419,7 @@ def init_routes(main_bp):
headers = {'Accept': 'application/json', 'Authorization': f'token {gitea_token}'}
# Gitea API: /api/v1/repos/{owner}/{repo}/commits/{branch}
commit_url = f"{gitea_url}/api/v1/repos/{gitea_repo}/commits/{deployed_branch}"
- commit_resp = requests.get(commit_url, headers=headers, timeout=5)
+ commit_resp = requests.get(commit_url, headers=headers, timeout=30) # Increased timeout to 30 seconds
if commit_resp.status_code == 200:
latest_version = commit_resp.json().get('sha')
except Exception as e:
diff --git a/static/js/launch_progress.js b/static/js/launch_progress.js
index fa2892a..6cbc7ba 100644
--- a/static/js/launch_progress.js
+++ b/static/js/launch_progress.js
@@ -571,40 +571,26 @@ async function startLaunch(data) {
saveDataStep.classList.add('completed');
saveDataStep.querySelector('.step-status').textContent = 'Successfully saved instance data';
- // Add instance details
- const instanceDetails = document.createElement('div');
- instanceDetails.className = 'mt-3';
- instanceDetails.innerHTML = `
-
-
-
Instance Information
-
-
-
- `;
- 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 = `
+
+ 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