Fixed queue items counter
This commit is contained in:
@@ -27,8 +27,31 @@ ACTIVE_TASK_STATES = {
|
||||
ProgressState.TRACK_PROGRESS, # "track_progress" - real-time track progress
|
||||
ProgressState.REAL_TIME, # "real_time" - real-time download progress
|
||||
ProgressState.RETRYING, # "retrying" - task is retrying after error
|
||||
"real-time", # "real-time" - real-time download progress (hyphenated version)
|
||||
}
|
||||
|
||||
def get_task_status_from_last_status(last_status):
|
||||
"""
|
||||
Extract the task status from last_status, checking both possible locations.
|
||||
|
||||
Args:
|
||||
last_status: The last status dict from get_last_task_status()
|
||||
|
||||
Returns:
|
||||
str: The task status string
|
||||
"""
|
||||
if not last_status:
|
||||
return "unknown"
|
||||
|
||||
# Check for status in nested status_info (for real-time downloads)
|
||||
status_info = last_status.get("status_info", {})
|
||||
if isinstance(status_info, dict) and "status" in status_info:
|
||||
return status_info["status"]
|
||||
|
||||
# Fall back to top-level status (for other task types)
|
||||
return last_status.get("status", "unknown")
|
||||
|
||||
|
||||
def is_task_active(task_status):
|
||||
"""
|
||||
Determine if a task is currently active (working/processing).
|
||||
@@ -138,7 +161,7 @@ def _build_task_response(task_info, last_status, task_id, current_time):
|
||||
# Determine last_line content
|
||||
if last_status and "raw_callback" in last_status:
|
||||
last_line_content = last_status["raw_callback"]
|
||||
elif last_status and last_status.get("status") == "error":
|
||||
elif last_status and get_task_status_from_last_status(last_status) == "error":
|
||||
last_line_content = _build_error_callback_object(last_status)
|
||||
else:
|
||||
last_line_content = last_status
|
||||
@@ -191,7 +214,7 @@ def get_paginated_tasks(page=1, limit=20, active_only=False):
|
||||
continue
|
||||
|
||||
last_status = get_last_task_status(task_id)
|
||||
task_status = last_status.get("status") if last_status else "unknown"
|
||||
task_status = get_task_status_from_last_status(last_status)
|
||||
is_active_task = is_task_active(task_status)
|
||||
|
||||
# Categorize tasks by status using ProgressState constants
|
||||
@@ -321,7 +344,7 @@ def get_task_details(task_id):
|
||||
# Determine last_line content
|
||||
if last_status and "raw_callback" in last_status:
|
||||
last_line_content = last_status["raw_callback"]
|
||||
elif last_status and last_status.get("status") == "error":
|
||||
elif last_status and get_task_status_from_last_status(last_status) == "error":
|
||||
last_line_content = _build_error_callback_object(last_status)
|
||||
else:
|
||||
# Fallback for non-error, no raw_callback, or if last_status is None
|
||||
@@ -405,7 +428,7 @@ def list_tasks():
|
||||
continue
|
||||
|
||||
last_status = get_last_task_status(task_id)
|
||||
task_status = last_status.get("status") if last_status else "unknown"
|
||||
task_status = get_task_status_from_last_status(last_status)
|
||||
is_active_task = is_task_active(task_status)
|
||||
|
||||
# Categorize tasks by status using ProgressState constants
|
||||
@@ -621,7 +644,7 @@ def get_task_updates():
|
||||
task_timestamp = last_status.get("timestamp") if last_status else task_info.get("created_at", 0)
|
||||
|
||||
# Determine task status and categorize
|
||||
task_status = last_status.get("status") if last_status else "unknown"
|
||||
task_status = get_task_status_from_last_status(last_status)
|
||||
is_active_task = is_task_active(task_status)
|
||||
|
||||
# Categorize tasks by status using ProgressState constants
|
||||
|
||||
@@ -510,7 +510,13 @@ export const Queue = () => {
|
||||
if (!context) return null;
|
||||
if (!isVisible) return null;
|
||||
|
||||
const hasActive = items.some((item) => !isTerminalStatus(item.status));
|
||||
const hasActive = items.some((item) => {
|
||||
// Check for status in both possible locations (nested status_info for real-time, or top-level for others)
|
||||
const actualStatus = (item.last_line?.status_info?.status as QueueStatus) ||
|
||||
(item.last_line?.status as QueueStatus) ||
|
||||
item.status;
|
||||
return isActiveTaskStatus(actualStatus);
|
||||
});
|
||||
const hasFinished = items.some((item) => isTerminalStatus(item.status));
|
||||
|
||||
// Handle mobile swipe-to-dismiss
|
||||
|
||||
@@ -55,9 +55,15 @@ export function QueueProvider({ children }: { children: ReactNode }) {
|
||||
const [totalTasks, setTotalTasks] = useState(0);
|
||||
const pageSize = 20; // Number of non-active tasks per page
|
||||
|
||||
// Calculate active downloads count
|
||||
// Calculate active downloads count (active + queued)
|
||||
const activeCount = useMemo(() => {
|
||||
return items.filter(item => !isTerminalStatus(item.status)).length;
|
||||
return items.filter(item => {
|
||||
// Check for status in both possible locations (nested status_info for real-time, or top-level for others)
|
||||
const actualStatus = (item.last_line?.status_info?.status as QueueStatus) ||
|
||||
(item.last_line?.status as QueueStatus) ||
|
||||
item.status;
|
||||
return isActiveTaskStatus(actualStatus);
|
||||
}).length;
|
||||
}, [items]);
|
||||
|
||||
const stopPolling = useCallback((internalId: string) => {
|
||||
@@ -156,15 +162,27 @@ export function QueueProvider({ children }: { children: ReactNode }) {
|
||||
total_tasks: number;
|
||||
active_tasks: number;
|
||||
updated_count: number;
|
||||
task_counts?: {
|
||||
active: number;
|
||||
queued: number;
|
||||
retrying: number;
|
||||
completed: number;
|
||||
error: number;
|
||||
cancelled: number;
|
||||
skipped: number;
|
||||
};
|
||||
}>(`/prgs/updates?since=${lastUpdateTimestamp.current}&active_only=true`);
|
||||
|
||||
const { tasks: updatedTasks, current_timestamp, total_tasks } = response.data;
|
||||
const { tasks: updatedTasks, current_timestamp, total_tasks, task_counts } = response.data;
|
||||
|
||||
// Update the last timestamp for next poll
|
||||
lastUpdateTimestamp.current = current_timestamp;
|
||||
|
||||
// Update total tasks count
|
||||
setTotalTasks(total_tasks || 0);
|
||||
// Update total tasks count - use active + queued if task_counts available
|
||||
const calculatedTotal = task_counts ?
|
||||
(task_counts.active + task_counts.queued) :
|
||||
(total_tasks || 0);
|
||||
setTotalTasks(calculatedTotal);
|
||||
|
||||
if (updatedTasks.length > 0) {
|
||||
console.log(`Smart polling: ${updatedTasks.length} tasks updated (${response.data.active_tasks} active) out of ${response.data.total_tasks} total`);
|
||||
@@ -236,6 +254,15 @@ export function QueueProvider({ children }: { children: ReactNode }) {
|
||||
pagination: {
|
||||
has_more: boolean;
|
||||
};
|
||||
task_counts?: {
|
||||
active: number;
|
||||
queued: number;
|
||||
retrying: number;
|
||||
completed: number;
|
||||
error: number;
|
||||
cancelled: number;
|
||||
skipped: number;
|
||||
};
|
||||
}>(`/prgs/list?page=${nextPage}&limit=${pageSize}`);
|
||||
|
||||
const { tasks: newTasks, pagination } = response.data;
|
||||
@@ -302,9 +329,18 @@ export function QueueProvider({ children }: { children: ReactNode }) {
|
||||
};
|
||||
total_tasks: number;
|
||||
timestamp: number;
|
||||
task_counts?: {
|
||||
active: number;
|
||||
queued: number;
|
||||
retrying: number;
|
||||
completed: number;
|
||||
error: number;
|
||||
cancelled: number;
|
||||
skipped: number;
|
||||
};
|
||||
}>(`/prgs/list?page=1&limit=${pageSize}`);
|
||||
|
||||
const { tasks, pagination, total_tasks, timestamp } = response.data;
|
||||
const { tasks, pagination, total_tasks, timestamp, task_counts } = response.data;
|
||||
|
||||
const backendItems = tasks
|
||||
.filter((task: any) => {
|
||||
@@ -329,7 +365,12 @@ export function QueueProvider({ children }: { children: ReactNode }) {
|
||||
|
||||
setItems(backendItems);
|
||||
setHasMore(pagination.has_more);
|
||||
setTotalTasks(total_tasks || 0);
|
||||
|
||||
// Update total tasks count - use active + queued if task_counts available
|
||||
const calculatedTotal = task_counts ?
|
||||
(task_counts.active + task_counts.queued) :
|
||||
(total_tasks || 0);
|
||||
setTotalTasks(calculatedTotal);
|
||||
|
||||
// Set initial timestamp to current time
|
||||
lastUpdateTimestamp.current = timestamp;
|
||||
@@ -489,7 +530,14 @@ export function QueueProvider({ children }: { children: ReactNode }) {
|
||||
}, []);
|
||||
|
||||
const cancelAll = useCallback(async () => {
|
||||
const activeItems = items.filter((item) => item.taskId && !isTerminalStatus(item.status));
|
||||
const activeItems = items.filter((item) => {
|
||||
if (!item.taskId) return false;
|
||||
// Check for status in both possible locations (nested status_info for real-time, or top-level for others)
|
||||
const actualStatus = (item.last_line?.status_info?.status as QueueStatus) ||
|
||||
(item.last_line?.status as QueueStatus) ||
|
||||
item.status;
|
||||
return isActiveTaskStatus(actualStatus);
|
||||
});
|
||||
if (activeItems.length === 0) {
|
||||
toast.info("No active downloads to cancel.");
|
||||
return;
|
||||
|
||||
@@ -18,8 +18,8 @@ export type QueueStatus =
|
||||
| "progress"
|
||||
| "track_progress";
|
||||
|
||||
// Active task statuses - tasks that are currently working/processing
|
||||
// This matches the ACTIVE_TASK_STATES constant in the backend
|
||||
// Active task statuses - tasks that are currently working/processing or queued
|
||||
// This matches the ACTIVE_TASK_STATES constant in the backend plus queued tasks
|
||||
export const ACTIVE_TASK_STATUSES: Set<QueueStatus> = new Set([
|
||||
"initializing", // task is starting up
|
||||
"processing", // task is being processed
|
||||
@@ -28,6 +28,7 @@ export const ACTIVE_TASK_STATUSES: Set<QueueStatus> = new Set([
|
||||
"track_progress", // real-time track progress
|
||||
"real-time", // real-time download progress
|
||||
"retrying", // task is retrying after error
|
||||
"queued", // task is queued and waiting to start
|
||||
]);
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user