Add real-time progress reporting for jobs with visual progress bars

parent 3790f911
...@@ -62,6 +62,69 @@ ...@@ -62,6 +62,69 @@
.catch(error => { .catch(error => {
console.log('Error updating job statuses:', error); console.log('Error updating job statuses:', error);
}); });
// Also update progress for processing jobs
updateJobProgress();
}
function updateJobProgress() {
// Update progress for all processing jobs
const processingJobs = document.querySelectorAll('[data-job-id]');
processingJobs.forEach(jobRow => {
const jobId = jobRow.getAttribute('data-job-id');
const statusElement = jobRow.querySelector('.job-status');
if (statusElement && statusElement.classList.contains('status-processing')) {
fetch(`/api/job_progress/${jobId}`)
.then(response => response.json())
.then(progressData => {
if (progressData && progressData.progress !== undefined) {
updateJobProgressDisplay(jobId, progressData);
}
})
.catch(error => {
console.log(`Error getting progress for job ${jobId}:`, error);
});
}
});
}
function updateJobProgressDisplay(jobId, progressData) {
const jobRow = document.querySelector(`[data-job-id="${jobId}"]`);
if (!jobRow) return;
const progressElement = jobRow.querySelector('.job-progress');
if (progressElement) {
const progressPercent = progressData.progress || 0;
const stage = progressData.stage || 'processing';
const message = progressData.message || '';
// Create progress bar
const progressBar = document.createElement('div');
progressBar.style.width = '100%';
progressBar.style.height = '8px';
progressBar.style.backgroundColor = '#e5e7eb';
progressBar.style.borderRadius = '4px';
progressBar.style.overflow = 'hidden';
progressBar.style.marginBottom = '4px';
const progressFill = document.createElement('div');
progressFill.style.width = `${progressPercent}%`;
progressFill.style.height = '100%';
progressFill.style.backgroundColor = '#3b82f6';
progressFill.style.transition = 'width 0.3s ease';
progressBar.appendChild(progressFill);
// Update progress text
const progressText = document.createElement('div');
progressText.style.fontSize = '0.75rem';
progressText.style.color = '#6b7280';
progressText.textContent = `${progressPercent}% - ${stage}: ${message}`;
progressElement.innerHTML = '';
progressElement.appendChild(progressBar);
progressElement.appendChild(progressText);
}
} }
function showJobCompletionNotification(jobId) { function showJobCompletionNotification(jobId) {
......
...@@ -565,6 +565,44 @@ def api_job_status_updates(): ...@@ -565,6 +565,44 @@ def api_job_status_updates():
return {'updates': updates} return {'updates': updates}
@app.route('/api/job_progress/<int:job_id>')
@login_required
def api_job_progress(job_id):
"""API endpoint for job progress updates."""
user = get_current_user_session()
# Get the job details
job = get_queue_status(job_id)
# Check if job belongs to user
if not job or job['user_id'] != user['id']:
return {'error': 'Job not found or access denied'}, 404
# Get progress from backend
try:
# Send get_progress request to backend
result_msg = Message('get_progress', str(uuid.uuid4()), {'job_id': job_id})
comm.send_message(result_msg)
# Try to receive response
response = comm.receive_message()
if response and response.msg_type == 'progress':
return {
'job_id': job_id,
'stage': response.data.get('stage', 'unknown'),
'progress': response.data.get('progress', 0),
'message': response.data.get('message', ''),
'timestamp': time.time()
}
elif response and response.msg_type == 'progress_pending':
return {'status': 'no_progress'}
else:
return {'status': 'no_progress'}
except Exception as e:
print(f"Error getting progress: {e}")
return {'status': 'error', 'message': str(e)}
@app.route('/update_settings', methods=['POST']) @app.route('/update_settings', methods=['POST'])
@login_required @login_required
def update_settings(): def update_settings():
......
...@@ -288,6 +288,17 @@ def analyze_media(media_path, prompt, model_path, interval=10, job_id=None, comm ...@@ -288,6 +288,17 @@ def analyze_media(media_path, prompt, model_path, interval=10, job_id=None, comm
return result, total_tokens return result, total_tokens
else: else:
print(f"DEBUG: Detected image, analyzing for job {job_id}") print(f"DEBUG: Detected image, analyzing for job {job_id}")
# Send progress update for image analysis
if comm:
progress_msg = Message('progress', f'progress_{job_id}', {
'job_id': job_id,
'stage': 'image_analysis',
'progress': 50,
'message': 'Analyzing image'
})
comm.send_message(progress_msg)
# Check for cancellation before processing image # Check for cancellation before processing image
if job_id and check_job_cancelled(job_id): if job_id and check_job_cancelled(job_id):
print(f"DEBUG: Job {job_id} cancelled before image analysis") print(f"DEBUG: Job {job_id} cancelled before image analysis")
...@@ -296,6 +307,17 @@ def analyze_media(media_path, prompt, model_path, interval=10, job_id=None, comm ...@@ -296,6 +307,17 @@ def analyze_media(media_path, prompt, model_path, interval=10, job_id=None, comm
result, tokens = analyze_single_image(media_path, full_prompt, model) result, tokens = analyze_single_image(media_path, full_prompt, model)
total_tokens += tokens total_tokens += tokens
print(f"DEBUG: Image analysis completed for job {job_id}") print(f"DEBUG: Image analysis completed for job {job_id}")
# Send final progress update
if comm:
progress_msg = Message('progress', f'progress_{job_id}', {
'job_id': job_id,
'stage': 'completed',
'progress': 100,
'message': 'Analysis completed'
})
comm.send_message(progress_msg)
torch.cuda.empty_cache() torch.cuda.empty_cache()
return result, total_tokens return result, total_tokens
def worker_process(backend_type: str): def worker_process(backend_type: str):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment