Référence
API
Breakout API

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_TOKEN

Endpoints

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 à traiter
  • threads (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

StatusDescription
pendingJob en attente de démarrage
runningBreakout en cours d'exécution
completedBreakout terminé avec succès
failedBreakout échoué (voir error pour détails)
cancelledJob annulé par utilisateur

Codes d'Erreur

CodeDescriptionSolution
DICTIONARY_NOT_FOUNDDictionnaire inexistantVérifier nom dictionnaire
TABLES_ALREADY_EXISTTables déjà crééesUtiliser overwrite=true
DB_CONNECTION_ERRORConnexion DB échouéeVérifier config DB
INVALID_THREADSNombre de threads invalideUtiliser 1-10 threads
INSUFFICIENT_PERMISSIONSPermissions insuffisantesVérifier droits user OAuth

Ressources


CSWeb Community Platform v2.0 - Breakout API Innovation : Assietou DIAGNE (ANSD, Sénégal)