refactor(queue): address code review feedback — extract constants and sync refresh interval
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
+1
-1
@@ -15,9 +15,9 @@ from app.api.logs import router as logs_router
|
||||
from app.api.onedrive import router as onedrive_router
|
||||
from app.api.openai import router as openai_router
|
||||
from app.api.process import router as process_router
|
||||
from app.api.queue import router as queue_router
|
||||
from app.api.search import router as search_router
|
||||
from app.api.settings import router as settings_router
|
||||
from app.api.queue import router as queue_router
|
||||
from app.api.url_upload import router as url_upload_router
|
||||
|
||||
# Import all the individual routers
|
||||
|
||||
+7
-3
@@ -20,6 +20,10 @@ from app.models import FileProcessingStep, FileRecord
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/queue", tags=["queue"])
|
||||
|
||||
# Constants
|
||||
CELERY_INSPECT_TIMEOUT = 2.0
|
||||
MAX_ARGS_DISPLAY_LENGTH = 200
|
||||
|
||||
|
||||
def _get_redis_queue_length(redis_client: redis.Redis, queue_name: str) -> int:
|
||||
"""Get the number of messages in a Redis-backed Celery queue.
|
||||
@@ -54,7 +58,7 @@ def _get_celery_inspect_stats() -> dict[str, Any]:
|
||||
}
|
||||
|
||||
try:
|
||||
inspector = celery.control.inspect(timeout=2.0)
|
||||
inspector = celery.control.inspect(timeout=CELERY_INSPECT_TIMEOUT)
|
||||
|
||||
active = inspector.active() or {}
|
||||
reserved = inspector.reserved() or {}
|
||||
@@ -68,7 +72,7 @@ def _get_celery_inspect_stats() -> dict[str, Any]:
|
||||
{
|
||||
"id": task.get("id", ""),
|
||||
"name": task.get("name", "unknown"),
|
||||
"args": str(task.get("args", []))[:200],
|
||||
"args": str(task.get("args", []))[:MAX_ARGS_DISPLAY_LENGTH],
|
||||
"started": task.get("time_start"),
|
||||
}
|
||||
)
|
||||
@@ -79,7 +83,7 @@ def _get_celery_inspect_stats() -> dict[str, Any]:
|
||||
{
|
||||
"id": task.get("id", ""),
|
||||
"name": task.get("name", "unknown"),
|
||||
"args": str(task.get("args", []))[:200],
|
||||
"args": str(task.get("args", []))[:MAX_ARGS_DISPLAY_LENGTH],
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
+51
@@ -437,6 +437,57 @@ Errors follow standard HTTP status codes with descriptive messages:
|
||||
}
|
||||
```
|
||||
|
||||
## Queue Monitoring
|
||||
|
||||
### GET /api/queue/stats
|
||||
|
||||
Get comprehensive queue and processing statistics, including Redis queue lengths, Celery worker inspection data, and database-level processing summaries.
|
||||
|
||||
**Authentication:** Required
|
||||
|
||||
**Response (200 OK):**
|
||||
```json
|
||||
{
|
||||
"queues": {
|
||||
"document_processor": 12,
|
||||
"default": 0,
|
||||
"celery": 0
|
||||
},
|
||||
"total_queued": 12,
|
||||
"celery": {
|
||||
"active": [
|
||||
{"id": "abc123", "name": "process_document", "args": "[42]", "started": 1700000000}
|
||||
],
|
||||
"reserved": [],
|
||||
"scheduled": [],
|
||||
"workers_online": 1
|
||||
},
|
||||
"db_summary": {
|
||||
"total_files": 5000,
|
||||
"processing": 3,
|
||||
"failed": 1,
|
||||
"completed": 4900,
|
||||
"pending": 96,
|
||||
"recent_processing": [
|
||||
{"file_id": 42, "filename": "invoice.pdf", "current_step": "extract_metadata_with_gpt"}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/queue/pending-count
|
||||
|
||||
Lightweight endpoint returning the total number of queued + in-progress items. Designed for the files page banner indicator.
|
||||
|
||||
**Authentication:** Required
|
||||
|
||||
**Response (200 OK):**
|
||||
```json
|
||||
{
|
||||
"total_pending": 15
|
||||
}
|
||||
```
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
The API implements rate limiting to ensure system stability. If you exceed the limits, you'll receive a `429 Too Many Requests` response.
|
||||
|
||||
@@ -92,6 +92,23 @@ The **Files** page provides access to all processed documents:
|
||||
3. Click on any file to view its details
|
||||
4. Sort the list by any column by clicking on the column header
|
||||
|
||||
> **Tip:** When documents are being processed, a blue banner appears at the top of the Files page showing how many items are queued or currently processing. Files will appear in the list once their processing completes. Admins can click "View Queue" in the banner to open the Queue Monitor dashboard.
|
||||
|
||||
## Queue Monitor (Admin)
|
||||
|
||||
The **Queue Monitor** dashboard provides real-time visibility into the document processing pipeline. It is available to admin users under **Admin → Queue Monitor** in the navigation bar.
|
||||
|
||||
The dashboard shows:
|
||||
- **Queued Tasks** — number of tasks waiting in Redis-backed Celery queues
|
||||
- **Active Tasks** — tasks currently being executed by Celery workers
|
||||
- **Files Processing** — files with at least one in-progress processing step
|
||||
- **Workers Online** — number of connected Celery worker processes
|
||||
- **Redis Queues** — per-queue breakdown of pending task counts
|
||||
- **Processing Pipeline** — database-level summary of file states (completed, processing, pending, failed)
|
||||
- **Recently Processing Files** — the most recent files being actively processed, with links to their detail pages
|
||||
|
||||
The dashboard auto-refreshes every 10 seconds.
|
||||
|
||||
## Searching Documents
|
||||
|
||||
DocuElevate provides two ways to search your documents:
|
||||
|
||||
@@ -189,6 +189,7 @@
|
||||
<script>
|
||||
(function () {
|
||||
const REFRESH_SECONDS = 10;
|
||||
document.getElementById('refreshInterval').textContent = REFRESH_SECONDS;
|
||||
let timer = null;
|
||||
|
||||
function escapeHtml(str) {
|
||||
|
||||
@@ -46,7 +46,12 @@ class TestGetCeleryInspectStats:
|
||||
"worker1": [{"id": "task-2", "name": "app.tasks.upload_to_s3.upload_to_s3", "args": [2]}]
|
||||
}
|
||||
mock_inspector.scheduled.return_value = {
|
||||
"worker1": [{"request": {"id": "task-3", "name": "app.tasks.check_credentials.check_credentials"}, "eta": "2026-01-01"}]
|
||||
"worker1": [
|
||||
{
|
||||
"request": {"id": "task-3", "name": "app.tasks.check_credentials.check_credentials"},
|
||||
"eta": "2026-01-01",
|
||||
}
|
||||
]
|
||||
}
|
||||
mock_celery_mod.control.inspect.return_value = mock_inspector
|
||||
|
||||
|
||||
Reference in New Issue
Block a user