シナリオの例 - AWS Flow Framework for Java

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

シナリオの例

後方互換性のない変更とみなされるコードのクラスの変更があります。このような変更には、スケジュールされたタスクの数値、型、または順序を変更する更新などがあります。次の例を考えます。

2 つのタイマータスクをスケジュールするには、ディサイダーコードを記述します。実行をスタートし、ディシジョンを実行します。その結果、2 つのタイマータスクは、ID 12 でスケジュールされます。

次のディシジョンが実行される前に、ディサイダーコードを更新して 1 つのタイマーのみスケジュールする場合、次のディシジョンタスク時、ID 2 は、コードが生成されたどのタイマータスクとも一致しないため、フレームワークで 2 番目の TimerFired イベントを再生することはできません。

シナリオの概要

このシナリオのステップを以下の概要に示します。シナリオの最終目標は、システムに移行して 1 つのタイマーのみスケジュールすることですが、移行前にスタートした実行が失敗することはありません。

  1. ディサイダーの初期バージョン

    1. ディサイダーを記述します。

    2. ディサイダーをスタートします。

    3. ディサイダーによって、2 つのタイマーがスケジュールされます。

    4. ディサイダーは、5 つの実行をスタートします。

    5. ディサイダーを停止します。

  2. 後方互換性のないディサイダーの変更

    1. ディサイダーを変更します。

    2. ディサイダーをスタートします。

    3. ディサイダーによって、1 つのタイマーがスケジュールされます。

    4. ディサイダーは、5 つの実行をスタートします。

次のセクションには、このシナリオの実装方法を示す Java コードの例が含まれます。解決方法 セクションのコード例は、後方互換性のない変更を修正するさまざまな方法を示します。

注記

このコードを実行するには、最新バージョンの AWS SDK for Java を使用します。

共通コード

次の Java コードによって、このシナリオの例が変更されることはありません。

SampleBase.java

package sample; import java.util.ArrayList; import java.util.List; import java.util.UUID; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow; import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClientBuilder; import com.amazonaws.services.simpleworkflow.flow.JsonDataConverter; import com.amazonaws.services.simpleworkflow.model.DescribeWorkflowExecutionRequest; import com.amazonaws.services.simpleworkflow.model.DomainAlreadyExistsException; import com.amazonaws.services.simpleworkflow.model.RegisterDomainRequest; import com.amazonaws.services.simpleworkflow.model.Run; import com.amazonaws.services.simpleworkflow.model.StartWorkflowExecutionRequest; import com.amazonaws.services.simpleworkflow.model.TaskList; import com.amazonaws.services.simpleworkflow.model.WorkflowExecution; import com.amazonaws.services.simpleworkflow.model.WorkflowExecutionDetail; import com.amazonaws.services.simpleworkflow.model.WorkflowType; public class SampleBase { protected String domain = "DeciderChangeSample"; protected String taskList = "DeciderChangeSample-" + UUID.randomUUID().toString(); protected AmazonSimpleWorkflow service = AmazonSimpleWorkflowClientBuilder.defaultClient(); { try { AmazonSimpleWorkflowClientBuilder.defaultClient().registerDomain(new RegisterDomainRequest().withName(domain).withDescription("desc").withWorkflowExecutionRetentionPeriodInDays("7")); } catch (DomainAlreadyExistsException e) { } } protected List<WorkflowExecution> workflowExecutions = new ArrayList<>(); protected void startFiveExecutions(String workflow, String version, Object input) { for (int i = 0; i < 5; i++) { String id = UUID.randomUUID().toString(); Run startWorkflowExecution = service.startWorkflowExecution( new StartWorkflowExecutionRequest().withDomain(domain).withTaskList(new TaskList().withName(taskList)).withInput(new JsonDataConverter().toData(new Object[] { input })).withWorkflowId(id).withWorkflowType(new WorkflowType().withName(workflow).withVersion(version))); workflowExecutions.add(new WorkflowExecution().withWorkflowId(id).withRunId(startWorkflowExecution.getRunId())); sleep(1000); } } protected void printExecutionResults() { waitForExecutionsToClose(); System.out.println("\nResults:"); for (WorkflowExecution wid : workflowExecutions) { WorkflowExecutionDetail details = service.describeWorkflowExecution(new DescribeWorkflowExecutionRequest().withDomain(domain).withExecution(wid)); System.out.println(wid.getWorkflowId() + " " + details.getExecutionInfo().getCloseStatus()); } } protected void waitForExecutionsToClose() { loop: while (true) { for (WorkflowExecution wid : workflowExecutions) { WorkflowExecutionDetail details = service.describeWorkflowExecution(new DescribeWorkflowExecutionRequest().withDomain(domain).withExecution(wid)); if ("OPEN".equals(details.getExecutionInfo().getExecutionStatus())) { sleep(1000); continue loop; } } return; } } protected void sleep(int millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }

Input.java

package sample; public class Input { private Boolean skipSecondTimer; public Input() { } public Input(Boolean skipSecondTimer) { this.skipSecondTimer = skipSecondTimer; } public Boolean getSkipSecondTimer() { return skipSecondTimer != null && skipSecondTimer; } public Input setSkipSecondTimer(Boolean skipSecondTimer) { this.skipSecondTimer = skipSecondTimer; return this; } }

最初のディサイダーコードを記述する

ディサイダーの最初の Java コードは以下のとおりです。これは、バージョン 1 として登録され、5 秒のタイマータスクが 2 つスケジュールされます。

InitialDecider.java

package sample.v1; import com.amazonaws.services.simpleworkflow.flow.DecisionContext; import com.amazonaws.services.simpleworkflow.flow.DecisionContextProviderImpl; import com.amazonaws.services.simpleworkflow.flow.WorkflowClock; import com.amazonaws.services.simpleworkflow.flow.annotations.Execute; import com.amazonaws.services.simpleworkflow.flow.annotations.Workflow; import com.amazonaws.services.simpleworkflow.flow.annotations.WorkflowRegistrationOptions; import sample.Input; @Workflow @WorkflowRegistrationOptions(defaultExecutionStartToCloseTimeoutSeconds = 60, defaultTaskStartToCloseTimeoutSeconds = 5) public interface Foo { @Execute(version = "1") public void sample(Input input); public static class Impl implements Foo { private DecisionContext decisionContext = new DecisionContextProviderImpl().getDecisionContext(); private WorkflowClock clock = decisionContext.getWorkflowClock(); @Override public void sample(Input input) { System.out.println("Decision (V1) WorkflowId: " + decisionContext.getWorkflowContext().getWorkflowExecution().getWorkflowId()); clock.createTimer(5); clock.createTimer(5); } } }

後方互換性のない変更のシミュレーション

次のディサイダーの変更された Java コードは、後方互換性のない変更を示す良い例です。コードは、バージョン 1 として登録されますが、スケジュールされるタイマーは 1 つのみです。

ModifiedDecider.java

package sample.v1.modified; import com.amazonaws.services.simpleworkflow.flow.DecisionContext; import com.amazonaws.services.simpleworkflow.flow.DecisionContextProviderImpl; import com.amazonaws.services.simpleworkflow.flow.WorkflowClock; import com.amazonaws.services.simpleworkflow.flow.annotations.Execute; import com.amazonaws.services.simpleworkflow.flow.annotations.Workflow; import com.amazonaws.services.simpleworkflow.flow.annotations.WorkflowRegistrationOptions; import sample.Input; @Workflow @WorkflowRegistrationOptions(defaultExecutionStartToCloseTimeoutSeconds = 60, defaultTaskStartToCloseTimeoutSeconds = 5) public interface Foo { @Execute(version = "1") public void sample(Input input); public static class Impl implements Foo { private DecisionContext decisionContext = new DecisionContextProviderImpl().getDecisionContext(); private WorkflowClock clock = decisionContext.getWorkflowClock(); @Override public void sample(Input input) { System.out.println("Decision (V1 modified) WorkflowId: " + decisionContext.getWorkflowContext().getWorkflowExecution().getWorkflowId()); clock.createTimer(5); } } }

次の Java コードでは、変更後のディサイダーを実行して、後方互換性のない変更が行われる問題をシミュレートします。

RunModifiedDecider.java

package sample; import com.amazonaws.services.simpleworkflow.flow.WorkflowWorker; public class BadChange extends SampleBase { public static void main(String[] args) throws Exception { new BadChange().run(); } public void run() throws Exception { // Start the first version of the decider WorkflowWorker before = new WorkflowWorker(service, domain, taskList); before.addWorkflowImplementationType(sample.v1.Foo.Impl.class); before.start(); // Start a few executions startFiveExecutions("Foo.sample", "1", new Input()); // Stop the first decider worker and wait a few seconds // for its pending pollers to match and return before.suspendPolling(); sleep(2000); // At this point, three executions are still open, with more decisions to make // Start the modified version of the decider WorkflowWorker after = new WorkflowWorker(service, domain, taskList); after.addWorkflowImplementationType(sample.v1.modified.Foo.Impl.class); after.start(); // Start a few more executions startFiveExecutions("Foo.sample", "1", new Input()); printExecutionResults(); } }

このプログラムを実行すると、失敗する 3 つの実行は、初期バージョンのディサイダーでスタートされ、移行後も継続します。