Implémentation de flux de travail - AWS Flow Framework pour Java

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.

Implémentation de flux de travail

Afin d'implémenter un flux de travail, vous écrivez une classe qui implémente l'interface @Workflow souhaitée. Par exemple, l'exemple d'interface de flux de travail (MyWorkflow) peut être implémentée comme suit :

public class MyWFImpl implements MyWorkflow { MyActivitiesClient client = new MyActivitiesClientImpl(); @Override public void startMyWF(int a, String b){ Promise<Integer> result = client.activity1(); client.activity2(result); } @Override public void signal1(int a, int b, String c){ //Process signal client.activity2(a + b); } }

La méthode @Execute dans cette classe est le point d'entrée de la logique de flux de travail. Étant donné que l'infrastructure utilise la reproduction pour reconstruire l'état d'objet lorsqu'une tâche de décision doit être traitée, un nouvel objet est créé pour chaque tâche de décision.

L'utilisation de Promise<T> en tant que paramètre n'est pas autorisée dans la méthode @Execute au sein d'une interface @Workflow, car la décision d'effectuer un appel asynchrone repose entièrement sur l'appelant. L'implémentation de flux de travail en elle-même ne varie pas selon que l'appel est synchrone ou asynchrone. Par conséquent, l'interface client générée possède des surcharges qui prennent des paramètres Promise<T>, afin que ces méthodes puissent être appelées de manière asynchrone.

Le type de retour d'une méthode @Execute peut uniquement être void ou Promise<T>. Notez que le type de retour du client externe correspondant est void et non pas Promise<>. Étant donné que le client externe ne doit pas être utilisé à partir du code asynchrone, le client externe ne renvoie pas d'objets Promise. Pour obtenir les résultats des exécutions de flux de travail indiquées en externe, vous pouvez concevoir le flux de travail pour mettre à jour l'état d'un magasin de données externes via une activité. Les API de visibilité d'Amazon SWF peuvent également être utilisées pour récupérer le résultat d'un flux de travail à des fins de diagnostic. Il n'est pas recommandé d'utiliser de manière générale les API de visibilité pour récupérer les résultats des exécutions de flux de travail, car ces appels d'API peuvent être limitée par Amazon SWF. Les API de visibilité exigent d'identifier l'exécution de flux de travail à l'aide d'une structure WorkflowExecution. Vous pouvez récupérer cette structure auprès du client de flux de travail généré en appelant la méthode getWorkflowExecution. Cette méthode renvoie la structure WorkflowExecution correspondant à l'exécution de flux de travail à laquelle le client est lié. ConsultezRéférence de l'API Amazon Simple Workflow Servicepour plus de détails sur l'API de visibilité.

Lorsque vous appelez des activités à partir de l'implémentation de votre flux de travail, vous devez utiliser le client d'activité généré. De même, pour envoyer des signaux, vous utilisez les clients de flux de travail générés.

Contexte décisionnel

L'infrastructure fournit un contexte ambiant chaque fois qu'un code de flux de travail est exécuté par l'infrastructure. Ce contexte fournit une fonctionnalité propre au contexte à laquelle vous pouvez accéder dans l'implémentation de votre flux de travail, comme la création d'un minuteur. Pour plus d'informations, consultez la section Contexte d'exécution.

Exposition de l'état d'exécution

Amazon SWF vous permet d'ajouter un état personnalisé dans l'historique de flux de travail. Le dernier état signalé par l'exécution de flux de travail vous est renvoyé via des appels de visibilité au service Amazon SWF et dans Amazon SWF Console. Par exemple, dans un flux de travail de traitement des commandes, vous pouvez signaler l'état de la commande à différentes étapes tel que « commande reçue », « commande expédiée », etc. DansAWS Flow Frameworkpour Java, cette opération s'effectue via une méthode sur votre interface de flux de travail qui est annotée avec@GetStateAnnotations. Lorsque le décideur a terminé de traiter une tâche de décision, il appelle cette méthode pour récupérer le dernier état de l'implémentation de flux de travail. Outre les appels de visibilité, l'état peut également être récupéré à l'aide du client externe généré (qui utilise les appels de visibilité en interne).

L'exemple suivant montre comment définir le contexte d'exécution.

@Workflow @WorkflowRegistrationOptions(defaultExecutionStartToCloseTimeoutSeconds = 60, defaultTaskStartToCloseTimeoutSeconds = 10) public interface PeriodicWorkflow { @Execute(version = "1.0") void periodicWorkflow(); @GetState String getState(); } @Activities(version = "1.0") @ActivityRegistrationOptions(defaultTaskScheduleToStartTimeoutSeconds = 300, defaultTaskStartToCloseTimeoutSeconds = 3600) public interface PeriodicActivity { void activity1(); } public class PeriodicWorkflowImpl implements PeriodicWorkflow { private DecisionContextProvider contextProvider = new DecisionContextProviderImpl(); private WorkflowClock clock = contextProvider.getDecisionContext().getWorkflowClock(); private PeriodicActivityClient activityClient = new PeriodicActivityClientImpl(); private String state; @Override public void periodicWorkflow() { state = "Just Started"; callPeriodicActivity(0); } @Asynchronous private void callPeriodicActivity(int count, Promise<?>... waitFor) { if(count == 100) { state = "Finished Processing"; return; } // call activity activityClient.activity1(); // Repeat the activity after 1 hour. Promise<Void> timer = clock.createTimer(3600); state = "Waiting for timer to fire. Count = "+count; callPeriodicActivity(count+1, timer); } @Override public String getState() { return state; } } public class PeriodicActivityImpl implements PeriodicActivity { @Override public static void activity1() { ... } }

Le client externe généré peut être utilisé pour récupérer à tout moment le dernier état de l'exécution de flux de travail.

PeriodicWorkflowClientExternal client = new PeriodicWorkflowClientExternalFactoryImpl().getClient(); System.out.println(client.getState());

Dans l'exemple ci-dessus, l'état d'exécution est signalé à différentes étapes. Lorsque l'instance de flux de travail démarre, periodicWorkflow signale l'état initial comme « Just Started » (Vient de démarrer). Chaque appel à callPeriodicActivity met à jour l'état de flux de travail. Une fois que activity1 a été appelé 100 fois, la méthode est renvoyée et l'instance de flux de travail se termine.

Locales de flux de travail

Il arrive que vous ayez besoin d'utiliser des variables statiques dans l'implémentation de votre flux de travail. Par exemple, il se peut que vous souhaitiez stocker un compteur accessible depuis plusieurs emplacements (éventuellement différentes classes) dans l'implémentation de flux de travail. Toutefois, vous ne pouvez pas compter sur les variables statiques de votre flux de travail car ces dernières sont partagées entre les threads, ce qui pose problème car un exécuteur peut traiter différentes tâches décisionnelles sur différents threads au même moment. Vous pouvez également stocker un tel état dans un champ sur l'implémentation de flux de travail, mais vous aurez ensuite besoin de distribuer l'objet d'implémentation. Pour répondre à ce besoin, l'infrastructure fournit une classe WorkflowExecutionLocal<?>. N'importe quel état ayant besoin d'une variable statique, comme des sémantiques, doit être conservé en tant que locale d'instance à l'aide de WorkflowExecutionLocal<?>. Vous pouvez déclarer et utiliser une variable statique de ce type. Par exemple, dans le code suivant, un objet WorkflowExecutionLocal<String> est utilisé pour stocker un nom d'utilisateur.

public class MyWFImpl implements MyWF { public static WorkflowExecutionLocal<String> username = new WorkflowExecutionLocal<String>(); @Override public void start(String username){ this.username.set(username); Processor p = new Processor(); p.updateLastLogin(); p.greetUser(); } public static WorkflowExecutionLocal<String> getUsername() { return username; } public static void setUsername(WorkflowExecutionLocal<String> username) { MyWFImpl.username = username; } } public class Processor { void updateLastLogin(){ UserActivitiesClient c = new UserActivitiesClientImpl(); c.refreshLastLogin(MyWFImpl.getUsername().get()); } void greetUser(){ GreetingActivitiesClient c = new GreetingActivitiesClientImpl(); c.greetUser(MyWFImpl.getUsername().get()); } }