163 lines
4.7 KiB
Plaintext
163 lines
4.7 KiB
Plaintext
---
|
|
description: need to create or find a job
|
|
globs:
|
|
alwaysApply: false
|
|
---
|
|
# Architecture des Jobs dans Mangarr
|
|
|
|
## Vue d'ensemble
|
|
|
|
Le système de jobs de Mangarr est conçu pour gérer les tâches asynchrones et de longue durée de manière uniforme à travers tous les domaines. Il est basé sur une architecture centralisée dans le domaine `Shared` et peut être étendu par chaque domaine spécifique.
|
|
|
|
## Structure
|
|
|
|
```
|
|
src/Domain/Shared/
|
|
├── Domain/
|
|
│ ├── Model/
|
|
│ │ ├── Job.php # Classe abstraite de base
|
|
│ │ ├── JobStatus.php # États possibles d'un job
|
|
│ │ └── FailedJob.php # Représentation d'un job échoué
|
|
│ ├── Contract/
|
|
│ │ ├── JobRepositoryInterface.php
|
|
│ │ └── FailedJobRepositoryInterface.php
|
|
│ └── Exception/
|
|
│ ├── JobNotFoundException.php
|
|
│ └── JobNotRetryableException.php
|
|
└── Infrastructure/
|
|
├── Persistence/
|
|
│ ├── Entity/
|
|
│ │ ├── JobEntity.php
|
|
│ │ └── FailedJobEntity.php
|
|
│ └── Repository/
|
|
│ ├── DoctrineJobRepository.php
|
|
│ └── DoctrineFailedJobRepository.php
|
|
└── Service/
|
|
└── JobRetryService.php
|
|
```
|
|
|
|
## Cycle de Vie d'un Job
|
|
|
|
### États Possibles
|
|
```php
|
|
enum JobStatus: string
|
|
{
|
|
case PENDING = 'pending'; // Job créé, en attente d'exécution
|
|
case IN_PROGRESS = 'in_progress';// Job en cours d'exécution
|
|
case COMPLETED = 'completed'; // Job terminé avec succès
|
|
case FAILED = 'failed'; // Job échoué définitivement
|
|
case CANCELLED = 'cancelled'; // Job annulé manuellement
|
|
}
|
|
```
|
|
|
|
### Transitions d'États
|
|
1. `PENDING` → `IN_PROGRESS` : Lors du démarrage du job
|
|
2. `IN_PROGRESS` → `COMPLETED` : Lorsque le job se termine avec succès
|
|
3. `IN_PROGRESS` → `FAILED` : Lorsque le job échoue et atteint le nombre maximum de tentatives
|
|
4. `IN_PROGRESS` → `PENDING` : Lorsque le job échoue mais peut être réessayé
|
|
5. Tout état → `CANCELLED` : Lorsque le job est annulé manuellement
|
|
|
|
## Création d'un Nouveau Type de Job
|
|
|
|
1. **Créer une classe de job spécifique**
|
|
```php
|
|
class MyCustomJob extends Job
|
|
{
|
|
public function __construct(
|
|
string $id,
|
|
public readonly string $someData,
|
|
public readonly array $additionalData = []
|
|
) {
|
|
parent::__construct($id, 'my_custom_job');
|
|
}
|
|
}
|
|
```
|
|
|
|
2. **Définir le Handler**
|
|
```php
|
|
class MyCustomJobHandler
|
|
{
|
|
public function __invoke(MyCustomJob $job): void
|
|
{
|
|
try {
|
|
$job->start();
|
|
// Logique métier
|
|
$job->complete();
|
|
} catch (\Exception $e) {
|
|
$job->fail($e->getMessage());
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Gestion des Échecs
|
|
|
|
### Retry Automatique
|
|
- Un job peut être réessayé tant que `$attempts < $maxAttempts`
|
|
- Lors d'un échec, si des tentatives sont encore possibles, le statut redevient `PENDING`
|
|
- Les informations d'échec sont conservées dans `FailedJob`
|
|
|
|
### Informations de Debug
|
|
Chaque job contient :
|
|
- `failureReason` : La raison de l'échec
|
|
- `attempts` : Nombre de tentatives effectuées
|
|
- `context` : Données contextuelles pour le debug
|
|
- `createdAt`, `startedAt`, `completedAt` : Timestamps pour le suivi
|
|
|
|
## Bonnes Pratiques
|
|
|
|
### 1. Création de Jobs
|
|
```php
|
|
$job = new MyCustomJob(
|
|
id: Uuid::v4(),
|
|
someData: 'data',
|
|
additionalData: ['key' => 'value']
|
|
);
|
|
```
|
|
|
|
### 2. Gestion du Contexte
|
|
```php
|
|
$job->context['important_info'] = 'value';
|
|
$job->context['debug_data'] = $debugInfo;
|
|
```
|
|
|
|
### 3. Retry Manuel
|
|
```php
|
|
if ($failedJob->canBeRetried()) {
|
|
$job->attempts = 0;
|
|
$job->status = JobStatus::PENDING;
|
|
$jobRepository->save($job);
|
|
}
|
|
```
|
|
|
|
### 4. Monitoring
|
|
- Utiliser `findByStatus()` pour surveiller les jobs par état
|
|
- Utiliser `findFailedJobs()` pour vérifier les échecs
|
|
- Consulter `FailedJob` pour les détails des échecs
|
|
|
|
## Règles Importantes
|
|
|
|
1. **Idempotence**
|
|
- Les jobs doivent être idempotents
|
|
- Gérer les cas de réexécution
|
|
- Vérifier l'état avant les opérations
|
|
|
|
2. **Contexte**
|
|
- Toujours fournir un contexte utile
|
|
- Inclure les IDs des entités concernées
|
|
- Ajouter des informations de debug pertinentes
|
|
|
|
3. **Durée**
|
|
- Les jobs doivent être de longue durée
|
|
- Pour les opérations courtes, utiliser des appels directs
|
|
- Prévoir des timeouts appropriés
|
|
|
|
4. **Statut**
|
|
- Ne jamais modifier le statut directement
|
|
- Utiliser les méthodes `start()`, `complete()`, `fail()`, `cancel()`
|
|
- Toujours sauvegarder après un changement de statut
|
|
|
|
5. **Échecs**
|
|
- Capturer et logger toutes les exceptions
|
|
- Fournir des messages d'erreur explicites
|
|
- Conserver le contexte d'échec pour le debug |