Implementazione del flusso di lavoro - AWS Flow Framework per Java

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Implementazione del flusso di lavoro

Per implementare un flusso di lavoro, scrivi una classe che implementa l'interfaccia @Workflow desiderata. Ad esempio, l'interfaccia del flusso di lavoro di esempio (MyWorkflow) può essere implementata come segue:

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); } }

Il metodo @Execute in questa classe è il punto di ingresso della logica del flusso di lavoro. Dato che il framework utilizza la riproduzione per ricostruire lo stato dell'oggetto quando un task di decisione deve essere elaborato, viene creato un nuovo oggetto per ciascun task di decisione.

L'utilizzo di Promise<T> come parametro non è consentito nel metodo @Execute in un'interfaccia @Workflow. Questo perché una chiamata asincrona è una decisione esclusiva dell'intermediario. L'implementazione del flusso di lavoro in sé non dipende dalla modalità di invocazione (sincrona o asincrona). Di conseguenza, l'interfaccia client generata ha overload che accettano i parametri Promise<T> in modo che questi metodi possano essere chiamati in modo asincrono.

Il tipo di restituzione di un metodo @Execute può essere solo void o Promise<T>. Ricorda che un tipo di restituzione del client esterno corrispondente è void e non Promise<>. Poiché il client esterno non deve essere utilizzato dal codice asincrono, il client esterno non restituisce oggetti Promise. Per ricevere i risultati delle esecuzioni del flusso di lavoro con stato esterno, puoi designare il flusso di lavoro per aggiornare lo stato in un data store esterno tramite un attività. Le API di visibilità di Amazon SWF possono anche essere utilizzate per recuperare il risultato di un flusso di lavoro a scopo diagnostico. Non conviene utilizzare le API di visibilità per recuperare le esecuzioni del flusso di lavoro come practice generale perché le chiamate API possono essere usate da Amazon SWF. Le API di visibilità ti richiedono di identificare l'esecuzione del flusso di lavoro con una struttura WorkflowExecution. Puoi ottenere questa struttura dal client di flusso di lavoro generato chiamando il metodo getWorkflowExecution. Questo metodo restituisce la struttura WorkflowExecution corrispondente all'esecuzione del flusso di lavoro a cui il client è legato. ConsultaRiferimento API di Amazon Simple Workflow Serviceper ulteriori dettagli sulle API di visibilità.

Quando chiami le attività dall'implementazione del flusso di lavoro, devi utilizzare il client di attività generato. Analogamente, per inviare segnali, devi utilizzare i client di flusso di lavoro generati.

Contesto di decisione

Il framework fornisce un contesto di ambiente ogni volta che il codice del flusso di lavoro viene eseguito dal framework. Questo contesto offre funzionalità specifiche a cui puoi accedere nell'implementazione del flusso di lavoro, ad esempio la creazione di un timer. Consulta la sezione relativa a Contesto di esecuzione per ulteriori informazioni.

Esposizione dello stato dell'esecuzione

Amazon SWF ti permette di aggiungere uno stato personalizzato alla cronologia del flusso di lavoro. L'ultimo stato riportato dall'esecuzione del flusso di lavoro ti viene restituito tramite chiamate di visibilità al servizio Amazon SWF e nella console di Amazon SWF. Ad esempio, in un flusso di lavoro di elaborazione dell'ordine, puoi segnalare lo stato dell'ordine in fasi diverse come "ordine ricevuto", ordine spedito" e così via. NellaAWS Flow Frameworkper Java, questo viene fatto tramite un metodo nell'interfaccia del flusso di lavoro che è annotata con@GetStateannotazione. Quando il decisore ha terminato l'elaborazione di un task di decisione, chiama il metodo per ricevere l'ultimo stato dall'implementazione del flusso di lavoro. A parte le chiamate di visibilità, lo stato può essere recuperato anche utilizzando il client esterno generato (che utilizza internamente le chiamate API di visibilità).

L'esempio seguente mostra come configurare il contesto di esecuzione.

@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() { ... } }

Si può utilizzare il client esterno generato per recuperare in qualsiasi momento l'ultimo stato dell'esecuzione del flusso di lavoro.

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

Nell'esempio precedente, lo stato di esecuzione è segnalato in varie fasi. Quando inizia l'istanza del flusso di lavoro, periodicWorkflow segnala lo stato iniziale come "Appena iniziata". Ogni chiamata a callPeriodicActivity aggiorna lo stato del flusso di lavoro. Una volta che activity1 è stata chiamata 100 volte, il metodo esegue la restituzione e l'istanza del flusso di lavoro è completata.

Locali del flusso di lavoro

A volte, puoi avere la necessità di utilizzare le variabili statiche nell'implementazione del flusso di lavoro. Ad esempio, puoi voler archiviare un contatore a cui è stato effettuato l'accesso da vari posti (forse classi diverse) nell'implementazione del flusso di lavoro. Tuttavia, non puoi affidarti a variabili statiche nei flussi di lavoro, perché le variabili statiche sono condivise tra i thread, il che rappresenta un problema, perché un lavoratore elabora task di decisione diversi su thread diversi nello stesso momento. In alternativa, puoi archiviare questo stato in un campo dell'implementazione del flusso di lavoro, ma poi devi trasferire l'oggetto dell'implementazione. A questo scopo, il framework fornisce una classe WorkflowExecutionLocal<?>. Ogni stato che deve avere una variabile statica come semantica deve essere mantenuto come istanza locale utilizzando WorkflowExecutionLocal<?>. Puoi dichiarare e utilizzare una variabile statica di questo tipo. Ad esempio, nel seguente frammento di codice, un WorkflowExecutionLocal<String> viene utilizzato per archiviare un nome utente.

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()); } }