# Phase 4C — Orchestration et synchronisation Live planifiée

Version introduite : **v0.11.0**.

Cette phase automatise l'exécution du moteur Live posé en v0.10.0. Elle ne rajoute aucun nouveau fournisseur et ne modifie aucune source existante.

## Objectif

Séparer clairement :

1. le **scheduler**, qui décide quand un fournisseur doit être synchronisé ;
2. la **file de jobs**, qui exécute le travail sans ralentir l'API ou l'administration ;
3. le **connecteur fournisseur**, qui sait réellement lire et convertir les données Live ;
4. `LiveDataService`, qui conserve l'historique et choisit l'état courant.

Le flux cible devient :

```text
Scheduler Laravel
      ↓
cw:live:dispatch
      ↓
SyncProviderLiveData (queue live)
      ↓
Connecteur Live compatible
      ↓
LiveDataService
      ↓
live_observations + attraction_live_states
      ↓
API /api/v1/.../live
```

## Sélection des fournisseurs

Le dispatcher ne considère que les fournisseurs :

- actifs ;
- ayant la capacité `wait_times` activée ;
- disposant d'un connecteur qui implémente `LiveSyncConnector`.

La cadence utilisée est `providers.poll_interval_seconds`. Si elle est absente, la valeur par défaut est 300 secondes.

Une fréquence inférieure à 60 secondes est volontairement refusée pour éviter les boucles agressives.

## Anti-doublons et concurrence

Chaque job Live est unique par fournisseur.

Deux protections sont utilisées :

- `ShouldBeUnique` empêche plusieurs copies du même job d'être mises simultanément en file ;
- `WithoutOverlapping` empêche deux traitements du même fournisseur de s'exécuter en parallèle.

Le dispatcher ignore également une synchronisation marquée `running` depuis moins de la durée de verrou configurée.

## Reprise sur erreur

Par défaut un job dispose de :

- 3 tentatives ;
- délais progressifs de 30 s, 120 s puis 300 s ;
- timeout de 60 s.

Une exception du connecteur :

- marque l'exécution courante comme `failed` dans `connector_runs` ;
- est relancée au système de queue afin que Laravel applique les nouvelles tentatives ;
- n'efface jamais le dernier état Live valide déjà présent en base.

## Journalisation

Chaque synchronisation crée une ligne `connector_runs` avec :

- fournisseur ;
- connecteur ;
- opération `live_sync` ;
- capacité `wait_times` ;
- statut ;
- durée ;
- statut HTTP éventuel ;
- nombre d'éléments reçus et acceptés ;
- source utilisée ;
- erreur éventuelle.

Aucun secret ou token n'est enregistré dans les métadonnées du run.

## Scheduler

La commande :

```bash
php artisan cw:live:dispatch
```

est planifiée chaque minute par Laravel.

Elle ne lance que les fournisseurs arrivés à échéance.

Pour forcer immédiatement tous les fournisseurs compatibles :

```bash
php artisan cw:live:dispatch --force
```

## Exécution locale Laragon

Deux processus doivent rester actifs pendant les tests automatiques :

```bash
php artisan schedule:work
```

et :

```bash
php artisan queue:work --queue=live,default
```

En production, le scheduler Laravel devra être déclenché par le mécanisme serveur habituel et un worker de queue devra rester actif.

## Administration

La page `/admin/live` affiche maintenant :

- fournisseurs actifs capables de fournir les temps d'attente ;
- connecteur configuré ;
- cadence ;
- compatibilité avec la synchronisation Live ;
- dernière synchronisation ;
- prochaine échéance ;
- bouton **Lancer la synchro**.

Le bouton n'exécute pas les appels distants dans la requête web : il met les jobs en file afin de préserver la stabilité de l'administration.

## Connecteurs actuels

`manual` et `generic_http` savent actuellement tester une connexion, mais ne savent pas encore convertir un flux Live en observations Coaster World. Ils apparaissent donc comme **Connecteur Live non disponible** dans la supervision.

C'est volontaire : la présente phase valide l'orchestration générique avant de brancher un parseur fournisseur réel.

## Configuration

Variables disponibles :

```text
CW_DATA_LIVE_SYNC_QUEUE=live
CW_DATA_LIVE_SYNC_INTERVAL=300
CW_DATA_LIVE_SYNC_MIN_INTERVAL=60
CW_DATA_LIVE_SYNC_RUNNING_LOCK=600
CW_DATA_LIVE_SYNC_UNIQUE_FOR=900
CW_DATA_LIVE_SYNC_JOB_TIMEOUT=60
CW_DATA_LIVE_SYNC_TRIES=3
```

Aucune variable n'est obligatoire : les valeurs par défaut sont compatibles avec l'installation actuelle.

## Hors périmètre

Cette phase ne fait pas encore :

- parsing Live ThemeParks.wiki ;
- parsing Queue-Times ;
- découverte automatique de nouvelles sources ;
- import automatique de parcs/attractions ;
- websocket temps réel ;
- prédiction d'attente.
