mirror of
https://github.com/karl0ss/ai_image_frame_server.git
synced 2025-08-12 20:58:28 +01:00
working queue logic
This commit is contained in:
parent
ff5dfbcbce
commit
3e46b3363b
@ -208,3 +208,54 @@ def get_queue_count() -> int:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Error fetching queue count: {e}")
|
logging.error(f"Error fetching queue count: {e}")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
def get_queue_details() -> list:
|
||||||
|
"""Fetches detailed queue information including model names and prompts."""
|
||||||
|
url = user_config["comfyui"]["comfyui_url"] + "/queue"
|
||||||
|
try:
|
||||||
|
response = requests.get(url)
|
||||||
|
response.raise_for_status()
|
||||||
|
data = response.json()
|
||||||
|
jobs = []
|
||||||
|
for job_list in [data.get("queue_running", []), data.get("queue_pending", [])]:
|
||||||
|
for job in job_list:
|
||||||
|
# Extract prompt data (format: [priority, time, prompt])
|
||||||
|
prompt_data = job[2]
|
||||||
|
model = "Unknown"
|
||||||
|
prompt = "No prompt"
|
||||||
|
|
||||||
|
# Find model loader node (works for SDXL/FLUX/Qwen workflows)
|
||||||
|
for node in prompt_data.values():
|
||||||
|
if node.get("class_type") in ["CheckpointLoaderSimple", "UnetLoaderGGUFAdvancedDisTorchMultiGPU"]:
|
||||||
|
model = node["inputs"].get("ckpt_name", "Unknown")
|
||||||
|
break
|
||||||
|
|
||||||
|
# Find prompt node using class_type pattern and title matching
|
||||||
|
for node in prompt_data.values():
|
||||||
|
class_type = node.get("class_type", "")
|
||||||
|
if "CLIPTextEncode" in class_type and "text" in node["inputs"]:
|
||||||
|
meta = node.get('_meta', {})
|
||||||
|
title = meta.get('title', '').lower()
|
||||||
|
if 'positive' in title or 'prompt' in title:
|
||||||
|
prompt = node["inputs"]["text"]
|
||||||
|
break
|
||||||
|
|
||||||
|
jobs.append({
|
||||||
|
"id": job[0],
|
||||||
|
"model": model.split(".")[0] if model != "Unknown" else model,
|
||||||
|
"prompt": prompt
|
||||||
|
})
|
||||||
|
return jobs
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Error fetching queue details: {e}")
|
||||||
|
return []
|
||||||
|
try:
|
||||||
|
response = requests.get(url)
|
||||||
|
response.raise_for_status()
|
||||||
|
data = response.json()
|
||||||
|
pending = len(data.get("queue_pending", []))
|
||||||
|
running = len(data.get("queue_running", []))
|
||||||
|
return pending + running
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Error fetching queue count: {e}")
|
||||||
|
return 0
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
from flask import Blueprint
|
from flask import Blueprint, jsonify
|
||||||
from libs.comfyui import cancel_current_job
|
from libs.comfyui import cancel_current_job, get_queue_details
|
||||||
|
|
||||||
bp = Blueprint("job_routes", __name__)
|
bp = Blueprint("job_routes", __name__)
|
||||||
|
|
||||||
@bp.route("/cancel", methods=["GET"])
|
@bp.route("/cancel", methods=["GET"])
|
||||||
def cancel_job():
|
def cancel_job():
|
||||||
return cancel_current_job()
|
return cancel_current_job()
|
||||||
|
|
||||||
|
@bp.route("/api/queue", methods=["GET"])
|
||||||
|
def api_queue():
|
||||||
|
return jsonify(get_queue_details())
|
||||||
|
@ -131,12 +131,54 @@
|
|||||||
height: 150px;
|
height: 150px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.queue-dropdown {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: 0;
|
||||||
|
background: #222;
|
||||||
|
border: 1px solid #444;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 10px;
|
||||||
|
z-index: 1001;
|
||||||
|
display: none;
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue-item {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
padding: 5px;
|
||||||
|
border-bottom: 1px solid #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue-item .model {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #00aaff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue-item .prompt {
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: #aaa;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div style="position: fixed; top: 20px; right: 20px; background: #333; padding: 5px 10px; border-radius: 5px; z-index: 1000;">
|
<div class="queue-container" style="position: fixed; top: 20px; right: 20px; z-index: 1000;">
|
||||||
Queue: {{ queue_count | default(0) }}
|
<button id="queue-btn" style="background: #333; color: white; border: none; padding: 5px 10px; border-radius: 5px; cursor: pointer;">
|
||||||
|
Queue: <span id="queue-count">{{ queue_count | default(0) }}</span>
|
||||||
|
</button>
|
||||||
|
<div id="queue-dropdown" class="queue-dropdown">
|
||||||
|
<!-- Queue items will be populated here -->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h1 style="margin-bottom: 20px;">Create An Image</h1>
|
<h1 style="margin-bottom: 20px;">Create An Image</h1>
|
||||||
|
|
||||||
@ -272,5 +314,60 @@
|
|||||||
alert("Error requesting random prompt: " + error);
|
alert("Error requesting random prompt: " + error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const queueBtn = document.getElementById('queue-btn');
|
||||||
|
const queueDropdown = document.getElementById('queue-dropdown');
|
||||||
|
const queueCountSpan = document.getElementById('queue-count');
|
||||||
|
|
||||||
|
// Toggle dropdown visibility
|
||||||
|
queueBtn.addEventListener('click', function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (queueDropdown.style.display === 'block') {
|
||||||
|
queueDropdown.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
fetchQueueDetails();
|
||||||
|
queueDropdown.style.display = 'block';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close dropdown when clicking outside
|
||||||
|
document.addEventListener('click', function() {
|
||||||
|
queueDropdown.style.display = 'none';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Prevent dropdown from closing when clicking inside it
|
||||||
|
queueDropdown.addEventListener('click', function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
|
function fetchQueueDetails() {
|
||||||
|
fetch('/api/queue')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(jobs => {
|
||||||
|
queueCountSpan.textContent = jobs.length;
|
||||||
|
const container = queueDropdown;
|
||||||
|
container.innerHTML = '';
|
||||||
|
|
||||||
|
if (jobs.length === 0) {
|
||||||
|
container.innerHTML = '<div class="queue-item">No jobs in queue</div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jobs.forEach(job => {
|
||||||
|
const item = document.createElement('div');
|
||||||
|
item.className = 'queue-item';
|
||||||
|
item.innerHTML = `
|
||||||
|
<div class="model">${job.model}</div>
|
||||||
|
<div class="prompt" title="${job.prompt}">${job.prompt}</div>
|
||||||
|
`;
|
||||||
|
container.appendChild(item);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error fetching queue:', error);
|
||||||
|
queueDropdown.innerHTML = '<div class="queue-item">Error loading queue</div>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user