Date: 17/01/2026 18:00 Status: IMPLEMENTE (17/01/2026 18:25) Priorité: HAUTE
Implémenter un système de queue pour gérer les requêtes IA de manière asynchrone en utilisant l'infrastructure existante :
┌─────────────────────────────────────────────────────────────────────────────┐
│ INFRASTRUCTURE EXISTANTE (prod-portainer 192.168.1.12) │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ supabase-db-prod │ │ redis-prod │ │ Loki │ │
│ │ PostgreSQL │ │ Queue Jobs │ │ Logs (30j) │ │
│ │ :5433 │ │ :6379 │ │ :3100 │ │
│ └──────────────────┘ └──────────────────┘ └──────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ O2switch │ │
│ │ Archive (90j) │ │
│ │ (sync 3h cron) │ │
│ └──────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ stock_8to (via NFS) │ │
│ │ /mnt/stock_8to/33800-stack/ai-data/jobs/ │ │
│ │ - inputs/ (images, audio uploadés) │ │
│ │ - outputs/ (fichiers générés) │ │
│ │ (backup horaire → stock_36to) │ │
│ └──────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ AI ORCHESTRATOR PHASE 3 │
│ │
│ Client (IP autorisée) │
│ │ POST /api/jobs │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ AI Orchestrator API (FastAPI :5501) │ │
│ │ │ │
│ │ 1. Valide input │ │
│ │ 2. Sauvegarde fichiers → stock_8to/ai-data/inputs/ │ │
│ │ 3. INSERT job → Supabase PostgreSQL │ │
│ │ 4. LPUSH job → Redis queue │ │
│ │ 5. Return job_id │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Worker (dans même container, asyncio) │ │
│ │ │ │
│ │ Loop: │ │
│ │ 1. BRPOP Redis queue │ │
│ │ 2. UPDATE job status=running → Supabase │ │
│ │ 3. Switch tool si nécessaire (via SSH win11) │ │
│ │ 4. Execute job (API Gradio) │ │
│ │ 5. Save output → stock_8to/ai-data/outputs/ │ │
│ │ 6. UPDATE job status=completed → Supabase │ │
│ │ 7. Log → Loki │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Win11 GPU │ │
│ │ (192.168.1.30) │ │
│ │ Bark/Music/ │ │
│ │ ComfyUI/etc │ │
│ └─────────────────┘ │
│ │
│ Dashboard (O2switch) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ ai-jobs.html │ │
│ │ - Fetch /api/queue (stats) │ │
│ │ - Fetch /api/jobs (history) │ │
│ │ - Via collect.sh (cron horaire existant) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
Se connecter à Supabase Studio : http://192.168.1.12:8201
ai_jobs-- Créer dans Supabase via Studio ou API
CREATE TABLE ai_jobs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Identification
tool_id VARCHAR(50) NOT NULL, -- bark, musicgen, comfyui, etc.
job_type VARCHAR(50) NOT NULL, -- tts, music, image, video
-- Status
status VARCHAR(20) NOT NULL DEFAULT 'pending',
priority INTEGER DEFAULT 0, -- -1=low, 0=normal, 1=high
-- Timing
created_at TIMESTAMPTZ DEFAULT NOW(),
started_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ,
-- Input (JSONB pour flexibilité)
input_params JSONB NOT NULL,
input_files TEXT[], -- Chemins relatifs dans ai-data/inputs/
-- Output
output_result JSONB,
output_files TEXT[], -- Chemins relatifs dans ai-data/outputs/
-- Metrics
processing_time_ms INTEGER,
vram_used_mb INTEGER,
-- Error
error_message TEXT,
retry_count INTEGER DEFAULT 0
);
-- Index pour requêtes dashboard
CREATE INDEX idx_ai_jobs_status ON ai_jobs(status);
CREATE INDEX idx_ai_jobs_created ON ai_jobs(created_at DESC);
# Queues (FIFO avec priorité)
ai:queue:high # Jobs prioritaires
ai:queue:normal # Jobs normaux
ai:queue:low # Jobs batch
# État
ai:current_job # Job ID en cours (pour dashboard)
ai:current_tool # Outil actif sur win11
{
"job_id": "uuid",
"tool_id": "bark",
"priority": 0
}
Les détails complets sont dans Supabase (pas dupliqués dans Redis).
/stock_8to/33800-stack/ai-data/
├── inputs/
│ └── {job_id}/
│ ├── source.jpg
│ └── audio.wav
├── outputs/
│ └── {job_id}/
│ ├── result.wav
│ └── result.png
└── temp/
└── (fichiers temporaires, nettoyés quotidiennement)
# === JOBS API ===
@app.post("/api/jobs")
async def create_job(job: JobCreate):
"""Créer un nouveau job dans la queue"""
# 1. Sauvegarder fichiers input si présents
# 2. INSERT dans Supabase
# 3. LPUSH dans Redis queue
# 4. Return job_id + position
@app.get("/api/jobs")
async def list_jobs(status: str = None, limit: int = 50):
"""Lister les jobs (pour dashboard)"""
# SELECT depuis Supabase avec filtres
@app.get("/api/jobs/{job_id}")
async def get_job(job_id: str):
"""Status détaillé d'un job"""
@app.delete("/api/jobs/{job_id}")
async def cancel_job(job_id: str):
"""Annuler un job pending"""
@app.get("/api/jobs/{job_id}/output/{filename}")
async def download_output(job_id: str, filename: str):
"""Télécharger fichier output"""
# Sert depuis stock_8to/ai-data/outputs/{job_id}/
# === QUEUE API ===
@app.get("/api/queue")
async def queue_status():
"""Stats queue pour dashboard"""
return {
"pending": redis.llen("ai:queue:*"),
"current_job": redis.get("ai:current_job"),
"current_tool": redis.get("ai:current_tool")
}
generate.d/20-ai-jobs.sh#!/bin/bash
# Génère ai-jobs.html avec stats depuis l'API
STATS=$(curl -s http://192.168.1.12:5501/api/queue)
JOBS=$(curl -s "http://192.168.1.12:5501/api/jobs?limit=50")
# Générer HTML avec les données...
<a href="ai-jobs.html">AI Jobs</a>
Le container ai-orchestrator envoie déjà ses logs à Loki (docker logging driver). Ajouter des logs structurés pour les jobs :
import logging
logger = logging.getLogger("ai-orchestrator")
# Pour chaque job
logger.info("job_started", extra={
"job_id": job_id,
"tool_id": tool_id,
"job_type": job_type
})
logger.info("job_completed", extra={
"job_id": job_id,
"processing_time_ms": elapsed,
"vram_used_mb": vram
})
Requête Grafana :
{container="ai-orchestrator"} |= "job_"
mkdir -p /stock_8to/33800-stack/ai-data/{inputs,outputs,temp}
main.pymain.py comme background task20-ai-jobs.shai-jobs.html(Réduit de 10h car utilisation infra existante)
| Service | Host | Port | Credentials |
|---|---|---|---|
| PostgreSQL | 192.168.1.12 | 5433 | Voir Supabase config |
| Redis | 192.168.1.12 | 6379 | Pas d'auth |
| stock_8to | /mnt/stock_8to | NFS | Monté sur prod-portainer |
| Loki | 192.168.1.12 | 3100 | Docker logging driver |
Validation requise avant implémentation