Breakout API API pour gérer le breakout sélectif des questionnaires CSPro.
Authentification Requise Toutes les requêtes nécessitent un Bearer token OAuth2.
Authorization: Bearer YOUR_ACCESS_TOKENEndpoints
POST /api/breakout/start Démarre un breakout sélectif pour un ou plusieurs dictionnaires.
Request Body:
{
"dictionaries": ["EVAL_DICT", "KAIROS_DICT"],
"threads": 5,
"overwrite": false
}Parameters:
dictionaries(array, required): Liste des dictionnaires à traiterthreads(integer, optional): Nombre de threads parallèles (défaut: 1)overwrite(boolean, optional): Écraser tables existantes (défaut: false)
Request:
curl -X POST http://localhost:8080/api/breakout/start \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"dictionaries": ["EVAL_DICT"],
"threads": 3,
"overwrite": false
}'Response (202 Accepted):
{
"status": "started",
"job_id": "breakout-20260315-120000",
"dictionaries": ["EVAL_DICT"],
"threads": 3,
"estimated_time": "45 minutes",
"message": "Breakout started in background"
}Response (409 Conflict):
{
"error": "Tables already exist",
"message": "Tables for dictionary 'EVAL_DICT' already exist. Use overwrite=true to replace.",
"existing_tables": ["eval_cases", "eval_producteurs"]
}GET /api/breakout/status/{job_id}
Récupère le statut d'un job de breakout.
Parameters:
job_id(path, required): ID du job (ex:breakout-20260315-120000)
Request:
curl -X GET http://localhost:8080/api/breakout/status/breakout-20260315-120000 \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Response (200 OK) - En cours:
{
"job_id": "breakout-20260315-120000",
"status": "running",
"progress": {
"dictionary": "EVAL_DICT",
"processed": 12500,
"total": 50000,
"percentage": 25,
"elapsed_time": "00:11:32",
"estimated_remaining": "00:34:28"
},
"threads": 3,
"started_at": "2026-03-15T12:00:00Z"
}Response (200 OK) - Terminé:
{
"job_id": "breakout-20260315-120000",
"status": "completed",
"result": {
"dictionaries_processed": ["EVAL_DICT"],
"total_cases": 50000,
"tables_created": ["eval_cases", "eval_producteurs", "eval_observations"],
"execution_time": "00:45:12"
},
"completed_at": "2026-03-15T12:45:12Z"
}Response (200 OK) - Erreur:
{
"job_id": "breakout-20260315-120000",
"status": "failed",
"error": {
"code": "DB_CONNECTION_ERROR",
"message": "Cannot connect to PostgreSQL server: Connection refused",
"details": "Host: postgres, Port: 5432"
},
"failed_at": "2026-03-15T12:05:30Z"
}GET /api/breakout/tables/{dictionary}
Liste les tables créées pour un dictionnaire.
Parameters:
dictionary(path, required): Nom du dictionnaire (ex:EVAL_DICT)
Request:
curl -X GET http://localhost:8080/api/breakout/tables/EVAL_DICT \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Response (200 OK):
{
"dictionary": "EVAL_DICT",
"label": "eval",
"database": "csweb_analytics",
"tables": [
{
"name": "eval_cases",
"type": "main",
"row_count": 50000,
"size": "12.5 MB"
},
{
"name": "eval_producteurs",
"type": "record",
"row_count": 75000,
"size": "18.2 MB"
},
{
"name": "eval_observations",
"type": "record",
"row_count": 150000,
"size": "35.8 MB"
}
],
"total_size": "66.5 MB",
"created_at": "2026-03-15T12:45:12Z"
}Response (404 Not Found):
{
"error": "No tables found",
"message": "No breakout tables found for dictionary 'EVAL_DICT'",
"suggestion": "Run breakout first using POST /api/breakout/start"
}DELETE /api/breakout/tables/{dictionary}
Supprime les tables d'un dictionnaire.
Request:
curl -X DELETE http://localhost:8080/api/breakout/tables/EVAL_DICT \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Response (200 OK):
{
"message": "Tables deleted successfully",
"dictionary": "EVAL_DICT",
"deleted_tables": ["eval_cases", "eval_producteurs", "eval_observations"],
"freed_space": "66.5 MB"
}GET /api/breakout/jobs Liste tous les jobs de breakout (actifs et terminés).
Query Parameters:
status(optional): Filtrer par statut (running,completed,failed)limit(optional): Nombre max de résultats (défaut: 50)
Request:
curl -X GET "http://localhost:8080/api/breakout/jobs?status=completed&limit=10" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Response (200 OK):
{
"total": 25,
"limit": 10,
"data": [
{
"job_id": "breakout-20260315-120000",
"status": "completed",
"dictionaries": ["EVAL_DICT"],
"cases_processed": 50000,
"execution_time": "00:45:12",
"started_at": "2026-03-15T12:00:00Z",
"completed_at": "2026-03-15T12:45:12Z"
},
{
"job_id": "breakout-20260314-100000",
"status": "completed",
"dictionaries": ["KAIROS_DICT"],
"cases_processed": 12000,
"execution_time": "00:18:30",
"started_at": "2026-03-14T10:00:00Z",
"completed_at": "2026-03-14T10:18:30Z"
}
]
}Exemples d'Utilisation
Java (Spring Boot)
@Service
@RequiredArgsConstructor
public class BreakoutService {
private final CSWebApiService cswebApi;
public String startBreakout(List<String> dictionaries, int threads) {
Map<String, Object> request = Map.of(
"dictionaries", dictionaries,
"threads", threads,
"overwrite", false
);
ResponseEntity<BreakoutJobResponse> response = cswebApi.post(
"/breakout/start",
request,
BreakoutJobResponse.class
);
return response.getBody().getJobId();
}
public BreakoutStatus getStatus(String jobId) {
ResponseEntity<BreakoutStatus> response = cswebApi.get(
"/breakout/status/" + jobId,
BreakoutStatus.class
);
return response.getBody();
}
}PHP (Laravel)
use App\Services\CSWebApiService;
class BreakoutController extends Controller
{
public function start(Request $request, CSWebApiService $cswebApi)
{
$data = [
'dictionaries' => $request->input('dictionaries'),
'threads' => $request->input('threads', 3),
'overwrite' => $request->input('overwrite', false),
];
$response = $cswebApi->post('/breakout/start', $data);
return response()->json($response);
}
public function status(string $jobId, CSWebApiService $cswebApi)
{
$status = $cswebApi->get("/breakout/status/{$jobId}");
return response()->json($status);
}
}JavaScript (Fetch API)
// Démarrer breakout
async function startBreakout(dictionaries, threads = 3) {
const response = await fetch('http://localhost:8080/api/breakout/start', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
dictionaries,
threads,
overwrite: false
})
});
const data = await response.json();
return data.job_id;
}
// Polling status
async function pollStatus(jobId) {
const interval = setInterval(async () => {
const response = await fetch(`http://localhost:8080/api/breakout/status/${jobId}`, {
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
const status = await response.json();
if (status.status === 'completed') {
clearInterval(interval);
console.log('Breakout completed!', status.result);
} else if (status.status === 'failed') {
clearInterval(interval);
console.error('Breakout failed:', status.error);
} else {
console.log(`Progress: ${status.progress.percentage}%`);
}
}, 5000); // Poll toutes les 5 secondes
}
// Utilisation
const jobId = await startBreakout(['EVAL_DICT'], 5);
pollStatus(jobId);Statuts de Job
| Status | Description |
|---|---|
pending | Job en attente de démarrage |
running | Breakout en cours d'exécution |
completed | Breakout terminé avec succès |
failed | Breakout échoué (voir error pour détails) |
cancelled | Job annulé par utilisateur |
Codes d'Erreur
| Code | Description | Solution |
|---|---|---|
DICTIONARY_NOT_FOUND | Dictionnaire inexistant | Vérifier nom dictionnaire |
TABLES_ALREADY_EXIST | Tables déjà créées | Utiliser overwrite=true |
DB_CONNECTION_ERROR | Connexion DB échouée | Vérifier config DB |
INVALID_THREADS | Nombre de threads invalide | Utiliser 1-10 threads |
INSUFFICIENT_PERMISSIONS | Permissions insuffisantes | Vérifier droits user OAuth |
Ressources
- CLI Command : CLI - process-cases-by-dict
- Breakout Guide : Guides - Breakout Sélectif
- OAuth Authentication : API - OAuth2
CSWeb Community Platform v2.0 - Breakout API Innovation : Assietou DIAGNE (ANSD, Sénégal)