

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Comprendre une tâche dans AWS Flow Framework for Java
<a name="details"></a>

**Topics**
+ [Tâche](#details.task)
+ [Ordre d'exécution](#details.order)
+ [Exécution de flux de travail](#details.workflow)
+ [Non-déterminisme](#details.non)

## Tâche
<a name="details.task"></a>

La primitive sous-jacente que Java utilise AWS Flow Framework pour gérer l'exécution du code asynchrone est la `Task` classe. Un objet de type `Task` représente le travail qui doit être effectué de manière asynchrone. Lorsque vous appelez une méthode asynchrone, l'infrastructure crée un objet `Task` pour exécuter le code dans cette méthode et le place dans une liste pour une exécution ultérieure. De même, lorsque vous appelez un objet `Activity`, un objet `Task` est créé. L'appel de méthode revient après cela, en revoyant généralement un objet `Promise<T>` comme futur résultat de l'appel.

La classe `Task` est publique et peut être utilisée directement. Par exemple, nous pouvons réécrire l'exemple Hello World pour utiliser un objet `Task` à la place d'une méthode asynchrone.

```
@Override
public void startHelloWorld(){
       final Promise<String> greeting = client.getName();
        new Task(greeting) {
        @Override
        protected void doExecute() throws Throwable {
        	client.printGreeting("Hello " + greeting.get() +"!");
        }
    };
}
```

L'infrastructure appelle la méthode `doExecute()` lorsque tous les objets `Promise` transmis au constructeur de l'objet `Task` sont prêts. Pour plus de détails sur la `Task` classe, consultez la AWS SDK pour Java documentation.

L'infrastructure inclut également une classe appelée `Functor` qui représente un objet `Task` qui est également un objet `Promise<T>`. L'objet `Functor` est prêt lorsque l'objet `Task` est terminé. Dans l'exemple suivant, un objet `Functor` est créé pour récupérer le message d'accueil :

```
Promise<String> greeting = new Functor<String>() {
    @Override
    protected Promise<String> doExecute() throws Throwable {
        return client.getGreeting();
    }
};
client.printGreeting(greeting);
```

## Ordre d'exécution
<a name="details.order"></a>

Les tâches deviennent éligibles à l'exécution uniquement lorsque tous les paramètres de type `Promise<T>`, transmis à la méthode ou activité asynchrone correspondante, sont prêts. Un objet `Task` prêt pour l'exécution est logiquement déplacé dans une file d'attente des processus prêts. En d'autres termes, elle est planifiée pour l'exécution. La classe de travail exécute la tâche en invoquant le code que vous avez écrit dans le corps de la méthode asynchrone ou en planifiant une tâche d'activité dans Amazon Simple Workflow Service (AWS) dans le cas d'une méthode d'activité. 

À mesure que les tâches s'exécutent et produisent des résultats, d'autres tâches deviennent prêtes et l'exécution du programme se poursuit. La manière dont l'infrastructure exécute les tâches est essentielle pour comprendre l'ordre dans lequel votre code asynchrone s'exécute. Un code qui apparaît séquentiellement dans votre programme peut ne pas s'exécuter dans cette ordre.

```
Promise<String> name = getUserName();
printHelloName(name);
printHelloWorld();
System.out.println("Hello, Amazon!");

@Asynchronous
private Promise<String> getUserName(){
	return Promise.asPromise("Bob");
}
@Asynchronous
private void printHelloName(Promise<String> name){
	System.out.println("Hello, " + name.get() + "!");
}
@Asynchronous
private void printHelloWorld(){
	System.out.println("Hello, World!");
}
```

Le code dans la liste ci-dessus imprimera les éléments suivants :

```
Hello, Amazon!
Hello, World!
Hello, Bob
```

Cela peut différer de vos attentes mais peut s'expliquer aisément en réfléchissant à la manière dont les tâches ont été exécutées pour les méthodes asynchrones :

1. L'appel à `getUserName` crée un objet `Task`. Appelons-le `Task1`. Parce qu'`getUserName`il ne prend aucun paramètre, `Task1` il est immédiatement placé dans la file d'attente prête.

1. Ensuite, l'appel à `printHelloName` crée un objet `Task` qui doit attendre le résultat de `getUserName`. Appelons-le `Task2`. Comme la valeur requise n'est pas encore prête, elle `Task2` est ajoutée à la liste d'attente.

1. Ensuite, une tâche pour ` printHelloWorld` est créée et ajoutée à la file d'attente des processus prêts. Appelons-le `Task3`.

1. La `println` déclaration affiche ensuite « Hello, Amazon \$1 » à la console.

1. À ce stade, les objets `Task1` et `Task3` sont placés dans la file d'attente des processus prêts et l'objet `Task2` dans la file d'attente.

1. L'application de travail exécute `Task1`, et son résultat rend `Task2` prêt. `Task2` se retrouve ajoutée à la file d'attente derrière `Task3`.

1. Les objets `Task3` et `Task2` sont ensuite exécutés dans cette ordre.

L'exécution des activités suit le même modèle. Lorsque vous appelez une méthode sur le client d'activité, celle-ci crée une méthode `Task` qui, lors de son exécution, planifie une activité dans Amazon SWF.

L'infrastructure s'appuie sur des fonctions comme la génération de code et les proxys dynamiques pour injecter la logique afin de convertir les appels de méthode en appels d'activité et tâches asynchrones dans votre programme.

## Exécution de flux de travail
<a name="details.workflow"></a>

L'exécution de l'implémentation de flux de travail est également gérée par la classe de l'exécuteur. Lorsque vous appelez une méthode sur le client de flux de travail, celui-ci appelle Amazon SWF pour créer une instance de flux de travail. Les tâches d'Amazon SWF ne doivent pas être confondues avec celles du framework. Dans Amazon SWF, une tâche est soit une tâche d'activité, soit une tâche de décision. L'exécution des tâches d'activité est simple. La classe Activity Worker reçoit les tâches d'activité d'Amazon SWF, invoque la méthode d'activité appropriée dans votre implémentation et renvoie le résultat à Amazon SWF.

L'exécution des tâches décisionnelles est plus impliquée. Le gestionnaire de flux de travail reçoit des tâches de décision d'Amazon SWF. Une tâche de décision demande à la logique de flux de travail ce qu'il faut faire ensuite. La première tâche de décision est générée pour une instance de flux de travail lorsqu'elle est lancée via le client de flux de travail. Lors de la réception de cette tâche de décision, l'infrastructure lance l'exécution du code dans la méthode de flux de travail annotée avec `@Execute`. Cette méthode exécute la logique de coordination qui planifie les activités. Lorsque l'état de l'instance de flux de travail change, par exemple lorsqu'une activité se termine, d'autres tâches décisionnelles sont planifiées. À ce stade, la logique de flux de travail peut décider d'entreprendre une action basée sur le résultat de l'activité ; par exemple, elle peut décider de planifier une autre activité.

L'infrastructure cache tous ces détails aux développeurs en traduisant sans heurts les tâches décisionnelles dans la logique de flux de travail. Du point de vue du développeur, le code ressemble à un programme normal. En guise de couverture, le framework l'associe aux appels à Amazon SWF et aux tâches de décision en utilisant l'historique géré par Amazon SWF. Lorsqu'une tâche de décision arrive, l'infrastructure reproduit la connexion de l'exécution du programme dans les résultats des activités terminées jusqu'à présent. Les méthodes et activités asynchrones qui attendaient ces résultats se débloquent, et l'exécution du programme se poursuit.

L'exécution de flux de travail de traitement de l'exemple d'image et de l'historique correspondant est illustrée dans le tableau suivant.


**Exécution de flux de travail miniatures**  

| Exécution du programme de flux de travail | Historique géré par Amazon SWF  | 
| --- | --- | 
| Exécution initiale | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazonswf/latest/awsflowguide/details.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazonswf/latest/awsflowguide/details.html)  | 
| Relire | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazonswf/latest/awsflowguide/details.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazonswf/latest/awsflowguide/details.html)  | 
| Relire | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazonswf/latest/awsflowguide/details.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazonswf/latest/awsflowguide/details.html)  | 
| Relire | 
|  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazonswf/latest/awsflowguide/details.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazonswf/latest/awsflowguide/details.html)  | 

Lorsqu'un appel `processImage` est effectué, le framework crée une nouvelle instance de flux de travail dans Amazon SWF. Il s'agit d'un enregistrement durable de l'instance de flux de travail lancée. Le programme s'exécute jusqu'à l'appel à l'`downloadImage`activité, qui demande à Amazon SWF de planifier une activité. Le flux de travail poursuit son exécution et crée des tâches pour les activités suivantes, mais elles ne peuvent pas être exécutées tant que l'`downloadImage`activité n'est pas terminée ; cet épisode de rediffusion prend donc fin. Amazon SWF répartit la tâche en fonction de l'`downloadImage`activité pour exécution, et une fois qu'elle est terminée, un enregistrement est enregistré dans l'historique avec le résultat. Le flux de travail est maintenant prêt à avancer et une tâche de décision est générée par Amazon SWF. L'infrastructure reçoit la tâche de décision et reproduit la connexion de flux de travail dans le résultat de l'image téléchargée comme enregistré dans l'historique. Cela permet de débloquer la tâche et de `createThumbnail` poursuivre l'exécution du programme en planifiant la tâche `createThumbnail` d'activité dans Amazon SWF. Le même processus se répète pour `uploadImage`. L'exécution du programme continue de cette façon jusqu'à ce que le flux de travail ait traité toutes les images et aucune tâche n'est en attente. Comme aucun état d'exécution n'est stocké localement, chaque tâche de décision peut être exécutée sur une machine différente. Cela vous permet d'écrire facilement des programmes tolérants aux pannes et évolutifs.

## Non-déterminisme
<a name="details.non"></a>

Comme le framework repose sur le replay, il est important que le code d'orchestration (tout le code du flux de travail à l'exception des implémentations d'activités) soit déterministe. Par exemple, le flux de contrôle dans votre programme ne doit pas dépendre d'un nombre aléatoire ou de l'heure actuelle. Comme ces éléments peuvent changer entre les invocations, il est possible que la rediffusion ne suive pas le même chemin dans la logique d'orchestration. Cela entraînera des résultats inattendus ou des erreurs. L'infrastructure fournit un objet `WorkflowClock` que vous pouvez utiliser pour obtenir l'heure actuelle de manière déterministe. Pour en savoir plus, consultez la section sur [Contexte d'exécution](executioncontext.md). 

**Note**  
Une connexion Spring incorrecte des objets d'implémentation de flux de travail peut également mener à un non-déterminisme . Les beans d'implémentations de flux de travail ainsi que les beans dont ils dépendent doivent être dans la portée de flux de travail (`WorkflowScope`). Par exemple, la connexion d'un bean d'implémentation de flux de travail à un bean qui conserve un état et se trouve dans un contexte global entraîne un comportement inattendu. Pour en savoir plus, consultez la section [Intégration de Spring](test.md#test.spring).