feat: debut du domain Shared avec Contracts et Jobs + rules pour cursor
This commit is contained in:
parent
19a697c712
commit
ca9a74fe69
163
.cursor/rules/jobs.mdc
Normal file
163
.cursor/rules/jobs.mdc
Normal file
@@ -0,0 +1,163 @@
|
||||
---
|
||||
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
|
||||
Reference in New Issue
Block a user