6.6 KiB
6.6 KiB
Runbook: Upload Stuck in "uploading" Status
Signal
Symptômes observables:
- Upload reste en statut
uploading> 10 minutes (anormal) - Utilisateur ne peut pas accéder au fichier uploadé
- Logs: Pas de transition
uploading→processing→completed - Métriques:
veza_file_uploads_total{status="uploading"}reste élevé
Endpoints concernés:
POST /api/v1/upload- Upload initialGET /api/v1/uploads/:id/status- Vérification statutGET /api/v1/tracks/:id- Accès track après upload
Hypothèses
- Job worker down - Worker qui traite les uploads ne fonctionne plus
- Queue bloquée - RabbitMQ/Job queue saturée ou bloquée
- Storage problème - Fichier non accessible, permissions, espace disque
- Processing échoué silencieusement - Erreur non loggée, statut non mis à jour
- Timeout processing - Traitement trop long, timeout avant completion
Vérifications
1. Vérifier statut upload spécifique
# Via API
curl -H "Authorization: Bearer <token>" \
http://localhost:8080/api/v1/uploads/<upload_id>/status
# Réponse attendue:
# {
# "success": true,
# "data": {
# "status": "uploading", # ← Bloqué ici
# "progress": 100,
# "created_at": "2025-12-15T10:00:00Z"
# }
# }
2. Vérifier logs application
# Chercher upload spécifique
grep "<upload_id>" /var/log/veza-backend-api/*.log
# Chercher erreurs processing
grep -i "upload.*error\|processing.*failed\|job.*failed" /var/log/veza-backend-api/*.log | tail -50
# Chercher jobs worker
grep -i "job worker\|process.*upload" /var/log/veza-backend-api/*.log | tail -50
3. Vérifier job worker
# Vérifier processus worker
ps aux | grep "job.*worker\|worker.*upload"
# Vérifier logs worker (si séparé)
tail -100 /var/log/veza-worker/*.log
4. Vérifier queue (RabbitMQ)
# Si RabbitMQ activé
rabbitmqctl list_queues name messages messages_ready messages_unacknowledged
# Vérifier connexion RabbitMQ
curl http://localhost:15672/api/queues # (si management activé)
5. Vérifier storage
# Vérifier fichier uploadé existe
ls -lh /var/veza/uploads/<upload_id>/
# Vérifier permissions
ls -la /var/veza/uploads/<upload_id>/
# Vérifier espace disque
df -h /var/veza/uploads
# Vérifier inodes (si problème)
df -i /var/veza/uploads
6. Vérifier base de données
-- Vérifier statut upload en DB
SELECT id, status, progress, created_at, updated_at, error_message
FROM uploads
WHERE id = '<upload_id>';
-- Chercher uploads bloqués (> 10 min en uploading)
SELECT id, status, created_at, updated_at
FROM uploads
WHERE status = 'uploading'
AND created_at < NOW() - INTERVAL '10 minutes'
ORDER BY created_at;
-- Vérifier jobs en attente
SELECT id, type, status, created_at, started_at, completed_at
FROM job_queue
WHERE type = 'process_upload'
AND status IN ('pending', 'processing')
ORDER BY created_at;
Actions Correctives
Si job worker down
-
Redémarrer job worker:
sudo systemctl restart veza-backend-api # ou docker restart veza-backend-api -
Vérifier worker démarre:
grep "Job Worker démarré" /var/log/veza-backend-api/*.log -
Relancer processing manuel (si possible):
- Via API admin (si disponible)
- Ou directement en DB (voir ci-dessous)
Si queue bloquée
-
Vérifier RabbitMQ:
sudo systemctl status rabbitmq-server # ou docker ps | grep rabbitmq -
Redémarrer RabbitMQ (si nécessaire):
sudo systemctl restart rabbitmq-server -
Purger queue (si nécessaire, ⚠️ perte jobs):
rabbitmqctl purge_queue <queue_name>
Si fichier manquant/inaccessible
-
Vérifier fichier existe:
find /var/veza/uploads -name "*<upload_id>*" -
Vérifier permissions:
chown -R veza:veza /var/veza/uploads/<upload_id>/ chmod -R 644 /var/veza/uploads/<upload_id>/ -
Si fichier manquant:
- Marquer upload comme
faileden DB - Notifier utilisateur
- Documenter perte fichier
- Marquer upload comme
Si processing échoué silencieusement
-
Forcer re-processing (via DB):
-- Marquer comme pending pour re-traitement UPDATE uploads SET status = 'pending', updated_at = NOW() WHERE id = '<upload_id>' AND status = 'uploading'; -- Ou créer job manuel INSERT INTO job_queue (id, type, payload, status, created_at) VALUES ( gen_random_uuid(), 'process_upload', jsonb_build_object('upload_id', '<upload_id>'), 'pending', NOW() ); -
Vérifier logs après re-processing:
tail -f /var/log/veza-backend-api/*.log | grep "<upload_id>"
Si timeout processing
-
Augmenter timeout (si configurable):
- Modifier timeout dans
internal/jobs/upload_processor.go - Redémarrer worker
- Modifier timeout dans
-
Diviser traitement (long terme):
- Implémenter processing par chunks
- Ajouter checkpoints
Actions Préventives
Monitoring à ajouter
-
Alerte uploads bloqués:
- alert: VezaUploadsStuck expr: | count(uploads{status="uploading", created_at < now() - 10m}) > 0 -
Métrique temps processing:
- Ajouter métrique
veza_upload_processing_duration_seconds - Alerter si > seuil (ex: 5 minutes)
- Ajouter métrique
Améliorations code
-
Timeout explicite:
- Ajouter timeout sur processing (ex: 10 min)
- Marquer comme
failedsi timeout
-
Retry logic:
- Implémenter retry automatique (max 3 tentatives)
- Backoff exponentiel
-
Health check job worker:
- Endpoint
/health/workervérifiant queue/jobs - Intégrer dans
/readyz
- Endpoint
Post-Mortem Notes
À documenter après résolution
- Upload ID affecté:
<upload_id> - Cause racine: Job worker down / Queue bloquée / Storage / Processing / Timeout
- Durée de l'incident: De [heure début] à [heure fin]
- Impact: Nombre d'uploads bloqués, utilisateurs affectés
- Actions prises: Liste des actions correctives
- Actions préventives:
- Ajouter monitoring uploads bloqués
- Implémenter timeout explicite
- Ajouter retry logic
- Améliorer logging processing
Métriques à surveiller post-incident
veza_file_uploads_total{status="uploading"}- Doit diminuerveza_file_uploads_total{status="completed"}- Doit augmenter- Temps moyen processing - Doit rester < 5 minutes
Références
- Handler upload:
internal/handlers/upload.go - Job processor:
internal/jobs/upload_processor.go(si existe) - Documentation upload async:
docs/UPLOAD_ASYNC.md