ワークフロー実装 - AWS Flow Framework Java 用

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

ワークフロー実装

ワークフローを実装するには、必要な @Workflow インターフェイスを実装するクラスを記述します。たとえば、ワークフローインターフェイス例 (MyWorkflow) を実装する場合は以下のとおりです。

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

このクラスの @Execute メソッドは、ワークフローロジックのエントリポイントです。フレームワークでは、決定タスクの処理時に再生を使用してオブジェクト状態を再構築するため、決定タスクごとに新しいオブジェクトが作成されます。

Promise<T> をパラメータとして使用することは、@Workflow インターフェイス内の @Execute メソッドでは禁止されています。これは非同期呼び出しが純粋に呼び出し元の決定に基づくためです。ワークフロー実装自体は、呼び出しが同期であるか非同期であるかに依存しません。したがって、生成されたクライアントインターフェイスのオーバーロードでは、これらのメソッドを非同期的に呼び出せるように Promise<T> パラメータを取ります。

@Execute メソッドの戻り値の型は、void または Promise<T> に限られます。対応する外部クライアントの戻り値の型は、void であり、Promise<> ではないことに注意してください。外部クライアントは、非同期コードからの使用を意図されていないため、Promise オブジェクトを返しません。外部で記述されているワークフロー実行の結果を取得するには、アクティビティを通じて外部データストアで状態を更新するようワークフローを設計できます。Amazon SWF の可視性 API は、診断目的でワークフローの結果を取得するためにも使用できます。一般的な操作として、可視性 API を使用してワークフロー実行の結果を取得することはお勧めできません。これらの API コールは Amazon SWF で調整される可能性があるためです。可視性 API では、WorkflowExecution 構造を使用してワークフロー実行を識別する必要があります。この構造は、getWorkflowExecution メソッドを呼び出して、生成されたワークフロークライアントから取得できます。このメソッドにより、クライアントがバインドされているワークフロー実行に対応する WorkflowExecution 構造が返されます。可視性 API に関する詳細については、「Amazon Simple Workflow Service API Reference」(Amazon Simple Workflow Service API リファレンス) を参照してください。

ワークフロー実装からアクティビティを呼び出す場合は、生成されたアクティビティクライアントを使用します。同様に、シグナルを送信するには、生成されたワークフロークライアントを使用します。

決定コンテキスト

フレームワークでは、ワークフローコードがフレームワークで実行されるたびに環境コンテキストを提供します。このコンテキスト固有の機能をワークフロー実装 (タイマーの作成など) で使用できます。詳細については、「実行コンテキスト」セクションを参照してください。

実行状態の公開

Amazon SWF では、カスタム状態をワークフロー履歴に追加できます。ワークフロー実行から報告される最新の状態は、可視性呼び出しを通じて Amazon SWF サービスと Amazon SWF コンソールに返されます。たとえば、注文処理ワークフローで「受注」、「注文出荷」などのさまざまなステージで注文のステータスを報告できます。AWS Flow Framework for Java では、これを @GetState 注釈が設定された、ワークフローインターフェイスのメソッドを通じて達成できます。ディサイダーは、決定タスクの処理を完了すると、このメソッドを呼び出してワークフロー実装から最新の状態を取得します。可視性呼び出しとは別に、生成された外部クライアント (内部で可視性 API コールを使用する) を使用して状態を取得することもできます。

次の例は、実行コンテキストの設定方法を示しています。

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

生成された外部クライアントを使用して、ワークフロー実行の最新状態をいつでも取得できます。

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

上の例で、実行状態はさまざまなステージで報告されます。ワークフローインスタンスが開始すると、periodicWorkflow は最初の状態を「Just Started」として報告します。次に、callPeriodicActivity に対する呼び出しごとにワークフロー状態が更新されます。activity1 が 100 回呼び出されると、このメソッドは戻り、ワークフローインスタンスが完了します。

ワークフローのローカル

ワークフロー実装で静的変数の使用が必要になる場合があります。たとえば、さまざまな場所 (さまざまなクラスなど) からアクセスされるカウンターをワークフローの実装に保存すると便利な場合があります。ただし、ワークフローの静的変数には依存できません。静的変数はスレッド間で共有されているため、ワーカーは複数の異なるスレッドで複数の異なる決定タスクを同時に処理することがあり、問題が生じます。または、そのような状態をワークフロー実装のフィールドに保存することもできますが、その場合は実装オブジェクトを多方面に渡す必要があります。このニーズに対処するには、フレームワークで WorkflowExecutionLocal<?> クラスを提供します。セマンティクスなどの静的変数を必要とする状態は、WorkflowExecutionLocal<?> を使用してインスタンスローカルとして保持します。このタイプの静的変数を宣言して使用できます。たとえば、次のスニペットでは、WorkflowExecutionLocal<String> を使用してユーザー名を保存しています。

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