Contoh skenario - AWS Flow Framework untuk Java

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Contoh skenario

Ada kelas perubahan kode yang dianggap tidak kompatibel ke belakang. Perubahan ini mencakup pembaruan yang mengubah nomor, jenis, atau urutan tugas terjadwal. Pertimbangkan contoh berikut:

Anda menulis kode decider untuk menjadwalkan dua tugas timer. Anda memulai eksekusi dan menjalankan keputusan. Akibatnya, dua tugas timer dijadwalkan, dengan ID 1 dan 2.

Jika Anda memperbarui kode penentu untuk menjadwalkan hanya satu timer sebelum keputusan berikutnya dieksekusi, selama tugas keputusan berikutnya, kerangka kerja akan gagal memutar ulang peristiwa TimerFired kedua, karena ID 2 tidak cocok dengan tugas timer apa pun yang dihasilkan kode.

Skenario

Garis besar berikut menunjukkan langkah-langkah skenario ini. Tujuan akhir dari skenario ini adalah untuk bermigrasi ke sistem yang hanya menjadwalkan satu timer tetapi tidak menyebabkan kegagalan dalam eksekusi yang dimulai sebelum migrasi.

  1. Versi Decider Awal

    1. Tulis decider.

    2. Mulai decider.

    3. Decider menjadwalkan dua timer.

    4. Decider mulai lima eksekusi.

    5. Hentikan decider.

  2. Perubahan Decider Tidak Kompatibel untuk Mundur

    1. Modifikasi decider.

    2. Mulai decider.

    3. Decider menjadwalkan satu timer.

    4. Decider mulai lima eksekusi.

Bagian berikut termasuk contoh kode Java yang menunjukkan bagaimana menerapkan skenario ini. Contoh kode di Solusi menunjukkan berbagai cara untuk memperbaiki perubahan yang tidak kompatibel ke belakang.

catatan

Anda dapat menggunakan versi terbaru AWS SDK for Java untuk menjalankan kode ini.

Kode Umum

Kode Java berikut tidak berubah di antara contoh-contoh dalam skenario ini.

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

Menulis Kode Decider Awal

Berikut ini adalah kode Java awal dari decider. Ini terdaftar sebagai versi 1 dan menjadwalkan dua tugas timer lima detik.

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

Mensimulasikan Perubahan yang Tidak Kompatibel untuk Mundur

Kode Java decider berikut yang dimodifikasi adalah contoh yang baik dari perubahan yang tidak kompatibel ke belakang. Kode ini masih terdaftar sebagai versi 1, tetapi hanya menjadwalkan satu timer.

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

Berikut kode Java memungkinkan Anda untuk mensimulasikan masalah membuat perubahan kebelakang yang kompatibel dengan menjalankan decider dimodifikasi.

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

Saat Anda menjalankan program, tiga eksekusi yang gagal adalah yang dimulai di bawah versi awal dari penentu dan dilanjutkan setelah migrasi.