

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

# Coba lagi Aktivitas Gagal
<a name="features-retry"></a>

Kegiatan kadang-kadang gagal karena alasan sementara, seperti kehilangan konektivitas sementara. Di lain waktu, aktivitas mungkin berhasil, sehingga cara yang tepat untuk menangani kegagalan aktivitas sering untuk mencoba lagi aktivitas, mungkin beberapa kali. 

Ada berbagai strategi untuk mencoba kembali aktivitas; yang terbaik tergantung pada detail alur kerja Anda. Strategi jatuh ke dalam tiga kategori dasar: 
+  retry-until-successStrategi hanya terus mencoba kembali aktivitas sampai selesai.
+ Strategi coba lagi eksponensial meningkatkan interval waktu antara coba lagi secara eksponensial sampai aktivitas selesai atau proses mencapai titik pemfilteran stopword tertentu, seperti jumlah maksimum upaya.
+ Strategi coba lagi kustom memutuskan apakah atau cara mencoba lagi aktivitas setelah setiap upaya gagal.

Bagian berikut menjelaskan cara menerapkan strategi ini. Contoh pekerja alur kerja semua menggunakan aktivitas tunggal, `unreliableActivity`, yang secara acak melakukan salah satu dari berikut ini: 
+ Selesaikan segera
+ Gagal sengaja dengan melebihi nilai waktu habis
+ Gagal sengaja dengan melempar `IllegalStateException` 

## Retry-Until-Success Strategi
<a name="features-retry-success"></a>

Strategi coba lagi yang paling sederhana adalah terus mencoba kembali aktivitas setiap kali gagal sampai akhirnya berhasil. Pola dasar adalah:

1. Menerapkan sebuah `TryCatch` bersarang atau kelas `TryCatchFinally` dalam metode titik masuk alur kerja Anda.

1. Jalankan aktivitas di `doTry`

1. Jika aktivitas gagal, kerangka kerja memanggil `doCatch`, yang menjalankan metode titik masuk lagi.

1. Ulangi Langkah 2 - 3 hingga aktivitas selesai dengan sukses.

Alur kerja berikut mengimplementasikan strategi. retry-until-success Antarmuka alur kerja diimplementasikan dalam `RetryActivityRecipeWorkflow` dan memiliki satu metode, `runUnreliableActivityTillSuccess`, yang merupakan titik masuk alur kerja. Pekerja alur kerja diimplementasikan dalam `RetryActivityRecipeWorkflowImpl`, sebagai berikut: 

```
public class RetryActivityRecipeWorkflowImpl
    implements RetryActivityRecipeWorkflow {

    @Override
    public void runUnreliableActivityTillSuccess() {
        final Settable<Boolean> retryActivity = new Settable<Boolean>();

        new TryCatch() {
            @Override
            protected void doTry() throws Throwable {
                Promise<Void> activityRanSuccessfully
                    = client.unreliableActivity();
                setRetryActivityToFalse(activityRanSuccessfully, retryActivity);
            }

            @Override
            protected void doCatch(Throwable e) throws Throwable {
                retryActivity.set(true);
            }
        };
        restartRunUnreliableActivityTillSuccess(retryActivity);
    }

    @Asynchronous
    private void setRetryActivityToFalse(
            Promise<Void> activityRanSuccessfully,
            @NoWait Settable<Boolean> retryActivity) {
        retryActivity.set(false);
    }

    @Asynchronous
    private void restartRunUnreliableActivityTillSuccess(
            Settable<Boolean> retryActivity) {
        if (retryActivity.get()) {
            runUnreliableActivityTillSuccess();
        }
    }
}
```

Alur kerja bekerja sebagai berikut: 

1. `runUnreliableActivityTillSuccess` membuat objek `Settable<Boolean>` bernama `retryActivity` yang digunakan untuk menunjukkan apakah aktivitas gagal dan harus dicoba lagi. `Settable<T>` berasal dari `Promise<T>` dan bekerja banyak dengan cara yang sama, tetapi Anda menetapkan nilai objek `Settable<T>` secara manual.

1. `runUnreliableActivityTillSuccess` mengimplementasikan sebuah kelas `TryCatch` bersarang anonim kelas untuk menangani setiap pengecualian yang dilemparkan oleh aktivitas `unreliableActivity`. Untuk diskusi lebih lanjut tentang cara menangani pengecualian dilemparkan oleh kode asinkron, lihat [Penanganan Kesalahan](errorhandling.md).

1. `doTry` mengeksekusi aktivitas `unreliableActivity`, yang mengembalikan objek `Promise<Void>` bernama `activityRanSuccessfully`.

1. `doTry` memanggil metode `setRetryActivityToFalse` asinkron, yang memiliki dua parameter:
   + `activityRanSuccessfully` mengambil objek `Promise<Void>` yang dikembalikan oleh aktivitas `unreliableActivity`.
   + `retryActivity` mengambil objek `retryActivity`.

   Jika `unreliableActivity` selesai, `activityRanSuccessfully` menjadi siap dan `setRetryActivityToFalse` mengatur `retryActivity` ke SALAH. Jika tidak, `activityRanSuccessfully` tidak pernah menjadi siap dan `setRetryActivityToFalse` tidak mengeksekusi.

1. Jika `unreliableActivity` melempar pengecualian, kerangka kerja memanggil `doCatch` dan meneruskan objek pengecualian. `doCatch` set `retryActivity` ke betul.

1. `runUnreliableActivityTillSuccess` memanggil metode `restartRunUnreliableActivityTillSuccess` asinkron dan meneruskannya objek `retryActivity`. Karena `retryActivity` adalah jenis `Promise<T>`, `restartRunUnreliableActivityTillSuccess` menunda eksekusi sampai `retryActivity` sudah siap, yang terjadi setelahnya `TryCatch` selesai. 

1. Saat `retryActivity` sudah siap, `restartRunUnreliableActivityTillSuccess` mengekstrak nilai.
   + Jika nilai adalah `false`, coba lagi berhasil. `restartRunUnreliableActivityTillSuccess` tidak dan urutan coba lagi berakhir.
   + Jika nilai benar, coba lagi gagal. `restartRunUnreliableActivityTillSuccess` memanggil `runUnreliableActivityTillSuccess` untuk menjalankan aktivitas lagi.

1. Langkah 1 - 7 ulangi sehingga `unreliableActivity` selesai. 

**catatan**  
`doCatch` tidak menangani pengecualian; itu hanya menetapkan objek `retryActivity` ke BETUL untuk menunjukkan bahwa aktivitas gagal. Coba lagi ditangani oleh metode `restartRunUnreliableActivityTillSuccess` asinkron, yang menunda eksekusi sampai `TryCatch` selesai. Alasan untuk pendekatan ini adalah bahwa, jika Anda mencoba kembali aktivitas di `doCatch`, Anda tidak dapat membatalkannya. Mencoba kembali aktivitas di `restartRunUnreliableActivityTillSuccess` mengizinkan Anda untuk melaksanakan kegiatan yang dapat dibatalkan. 

## Strategi Coba Kembali Eksponensial
<a name="features-retry-exponential"></a>

Dengan strategi coba lagi eksponensial, kerangka kerja mengeksekusi aktivitas gagal lagi setelah jangka waktu tertentu, N detik. Jika upaya gagal kerangka kerja mengeksekusi aktivitas lagi setelah 2N detik, dan kemudian 4N detik dan seterusnya. Karena waktu tunggu bisa mendapatkan cukup besar, Anda biasanya menghentikan upaya coba lagi di beberapa titik daripada berlanjut tanpa batas..

Kerangka kerja ini menyediakan tiga cara untuk menerapkan strategi coba lagi eksponensial:
+ Anotasi `@ExponentialRetry` adalah pendekatan yang paling sederhana, tetapi Anda harus mengatur opsi konfigurasi coba lagi pada waktu kompilasi.
+ Kelas `RetryDecorator` mengizinkan Anda untuk mengatur konfigurasi coba lagi pada waktu aktif dan mengubahnya sesuai kebutuhan.
+ Kelas `AsyncRetryingExecutor` mengizinkan Anda untuk mengatur konfigurasi coba lagi pada waktu aktif dan mengubahnya sesuai kebutuhan. Selain itu, kerangka kerja memanggil metode `AsyncRunnable.run` yang diimplementasikan pengguna untuk menjalankan setiap upaya coba lagi.

Semua pendekatan mendukung opsi konfigurasi berikut, di mana nilai waktu dalam detik: 
+ Waktu tunggu percobaan ulang awal.
+ Koefisien back-off, yang digunakan untuk komputasi interval coba lagi, sebagai berikut:

  ```
  retryInterval = initialRetryIntervalSeconds * Math.pow(backoffCoefficient, numberOfTries - 2)
  ```

  Nilai default adalah 2.0.
+ Jumlah maksimum upaya coba lagi. Nilai default tidak terbatas.
+ Interval coba lagi maksimum. Nilai default tidak terbatas.
+ Waktu kedaluwarsa. Coba lagi upaya berhenti ketika total durasi proses melebihi nilai ini. Nilai default tidak terbatas.
+ Pengecualian yang akan memicu proses coba lagi. Secara default, setiap pengecualian memicu proses coba lagi.
+ Pengecualian yang tidak akan memicu upaya coba lagi. Secara default, tidak ada pengecualian yang dikecualikan.

Bagian berikut menjelaskan berbagai cara yang Anda dapat menerapkan strategi coba lagi eksponensial.

### Coba lagi eksponensial dengan @ ExponentialRetry
<a name="features-retry-exponential-annotation"></a>

Cara termudah untuk menerapkan strategi coba lagi eksponensial untuk suatu kegiatan adalah dengan menerapkan anotasi `@ExponentialRetry ` untuk aktivitas dalam definisi antarmuka. Jika aktivitas gagal, kerangka kerja menangani proses coba lagi secara otomatis, berdasarkan nilai opsi yang ditentukan. Pola dasar adalah:

1. Terapkan `@ExponentialRetry` untuk aktivitas yang sesuai dan menentukan konfigurasi coba lagi.

1. Jika aktivitas dijelaskan gagal, kerangka kerja secara otomatis mencoba ulang aktivitas sesuai dengan konfigurasi yang ditentukan oleh argumen penjelasan ini. 

Pekerja alur kerja `ExponentialRetryAnnotationWorkflow` mengimplementasikan strategi coba lagi eksponensial dengan menggunakan anotasi `@ExponentialRetry`. anotasi tersebut menggunakan aktivitas `unreliableActivity` yang definisi antarmukanya diimplementasikan dalam `ExponentialRetryAnnotationActivities` sebagai berikut:

```
@Activities(version = "1.0")
@ActivityRegistrationOptions(
    defaultTaskScheduleToStartTimeoutSeconds = 30,
    defaultTaskStartToCloseTimeoutSeconds = 30)
public interface ExponentialRetryAnnotationActivities {
    @ExponentialRetry(
        initialRetryIntervalSeconds = 5,
        maximumAttempts = 5,
        exceptionsToRetry = IllegalStateException.class)
    public void unreliableActivity();
}
```

Opsi `@ExponentialRetry` menentukan strategi berikut: 
+ Coba lagi hanya jika aktivitas melempar `IllegalStateException`.
+ Gunakan waktu tunggu awal 5 detik.
+ Tidak lebih dari 5 upaya coba lagi. 

Antarmuka alur kerja diimplementasikan dalam `RetryWorkflow` dan memiliki satu metode, `process`, yang merupakan titik masuk alur kerja. Pekerja alur kerja diimplementasikan dalam `ExponentialRetryAnnotationWorkflowImpl`, sebagai berikut: 

```
public class ExponentialRetryAnnotationWorkflowImpl implements RetryWorkflow {
    public void process() {
        handleUnreliableActivity();
    }

    public void handleUnreliableActivity() {
        client.unreliableActivity();
    }
}
```

Alur kerja bekerja sebagai berikut: 

1. `process` menjalankan metode `handleUnreliableActivity` sinkron.

1. `handleUnreliableActivity` mengeksekusi aktivitas `unreliableActivity`. 

Jika aktivitas gagal dengan melempar `IllegalStateException`, kerangka kerja secara otomatis menjalankan strategi coba lagi yang ditentukan dalam `ExponentialRetryAnnotationActivities`.

### Coba Ulang Eksponensial dengan Kelas RetryDecorator
<a name="features-retry-exponential-decorator"></a>

`@ExponentialRetry` mudah digunakan. Namun, konfigurasi statis dan ditetapkan pada waktu kompilasi, sehingga kerangka kerja menggunakan strategi coba lagi yang sama setiap kali aktivitas gagal. Anda dapat menerapkan strategi coba lagi eksponensial yang lebih fleksibel dengan menggunakan kelas `RetryDecorator`, yang mengizinkan Anda untuk menentukan konfigurasi pada waktu aktif dan mengubahnya sesuai kebutuhan. Pola dasar adalah:

1. Buat dan konfigurasi objek `ExponentialRetryPolicy` yang menentukan konfigurasi coba lagi.

1. Buat objek `RetryDecorator` dan melalui objek `ExponentialRetryPolicy` dari Langkah 1 untuk konstruktor.

1. Terapkan objek dekorator untuk aktivitas dengan melewati nama kelas klien aktivitas ke objek `RetryDecorator` menghiasi metode.

1. Mengeksekusi aktivitas.

Jika aktivitas gagal, kerangka kerja mencoba ulang aktivitas sesuai dengan konfigurasi objek `ExponentialRetryPolicy`. Anda dapat mengubah konfigurasi coba lagi yang diperlukan dengan memodifikasi objek ini. 

**catatan**  
Anotasi `@ExponentialRetry` dan kelas `RetryDecorator` sama-sama eksklusif. Anda tidak dapat menggunakan `RetryDecorator` untuk secara dinamis mengesampingkan kebijakan coba lagi yang ditentukan oleh anotasi `@ExponentialRetry`. 

Implementasi alur kerja berikut menunjukkan cara menggunakan kelas `RetryDecorator` untuk menerapkan strategi coba lagi eksponensial. Implementasi menggunakan aktivitas `unreliableActivity` yang tidak memiliki anotasi `@ExponentialRetry`. Antarmuka alur kerja diimplementasikan dalam `RetryWorkflow` dan memiliki satu metode, `process`, yang merupakan titik masuk alur kerja. Pekerja alur kerja diimplementasikan dalam `DecoratorRetryWorkflowImpl`, sebagai berikut: 

```
public class DecoratorRetryWorkflowImpl implements RetryWorkflow {
   ...
  public void process() {
      long initialRetryIntervalSeconds = 5;
      int maximumAttempts = 5;
      ExponentialRetryPolicy retryPolicy = new ExponentialRetryPolicy(
              initialRetryIntervalSeconds).withMaximumAttempts(maximumAttempts);

      Decorator retryDecorator = new RetryDecorator(retryPolicy);
      client = retryDecorator.decorate(RetryActivitiesClient.class, client);
      handleUnreliableActivity();
  }

  public void handleUnreliableActivity() {
      client.unreliableActivity();
  }
}
```

Alur kerja bekerja sebagai berikut: 

1. `process` membuat dan mengkonfigurasi objek `ExponentialRetryPolicy` oleh: 
   + Melewati interval coba lagi awal untuk konstruktor.
   + Memanggil metode objek `withMaximumAttempts` untuk mengatur jumlah maksimum upaya untuk 5. `ExponentialRetryPolicy` mengekspos lainnya objek `with` yang dapat Anda gunakan untuk menentukan opsi konfigurasi lainnya.

1. `process` membuat objek `RetryDecorator` bernama `retryDecorator` dan meneruskan objek `ExponentialRetryPolicy` dari Langkah 1 ke konstruktor.

1. `process` menerapkan dekorator untuk aktivitas dengan memanggil metode `retryDecorator.decorate` dan meneruskan itu nama kelas aktivitas klien.

1. `handleUnreliableActivity` mengeksekusi aktivitas. 

Jika aktivitas gagal, kerangka kerja coba lagi sesuai dengan konfigurasi yang ditentukan pada Langkah 1.

**catatan**  
Beberapa `ExponentialRetryPolicy` metode kelas `with` memiliki metode `set` yang sesuai yang dapat Anda hubungi untuk mengubah opsi konfigurasi yang sesuai setiap saat: `setBackoffCoefficient`, `setMaximumAttempts`, `setMaximumRetryIntervalSeconds`, dan `setMaximumRetryExpirationIntervalSeconds`. 

### Coba Ulang Eksponensial dengan Kelas AsyncRetryingExecutor
<a name="features-retry-exponential-async"></a>

Kelas `RetryDecorator` menyediakan lebih banyak fleksibilitas dalam mengkonfigurasi proses coba lagi daripada `@ExponentialRetry`, namun kerangka kerja masih menjalankan upaya coba lagi secara otomatis, berdasarkan objek konfigurasi `ExponentialRetryPolicy` saat ini. Pendekatan yang lebih fleksibel adalah dengan menggunakan kelas `AsyncRetryingExecutor`. Selain mengizinkan Anda untuk mengkonfigurasi proses coba lagi pada waktu aktif, kerangka kerja memanggil metode `AsyncRunnable.run` yang diimplementasikan pengguna untuk menjalankan setiap upaya coba lagi bukan hanya mengeksekusi aktivitas.

Pola dasar adalah: 

1. Buat dan konfigurasikan objek `ExponentialRetryPolicy` untuk menentukan konfigurasi coba lagi.

1. Buat objek `AsyncRetryingExecutor`, dan meneruskannya objek `ExponentialRetryPolicy` dan sebuah instans dari jam alur kerja.

1.  Menerapkan sebuah `TryCatch` bersarang anonim atau kelas `TryCatchFinally`.

1. Menerapkan kelas `AsyncRunnable` anonim dan menimpa metode `run` untuk menerapkan kode kustom untuk menjalankan aktivitas.

1.  Ganti `doTry` untuk memanggil `AsyncRetryingExecutor` metode `execute` objek dan meneruskannya kelas `AsyncRunnable` dari Langkah 4. Objek `AsyncRetryingExecutor` memanggil `AsyncRunnable.run` untuk menjalankan aktivitas.

1. Jika aktivitas gagal, objek `AsyncRetryingExecutor` memanggil metode `AsyncRunnable.run` lagi, sesuai dengan kebijakan coba lagi yang ditentukan pada Langkah 1. 

Alur kerja berikut menunjukkan cara menggunakan kelas `AsyncRetryingExecutor` untuk menerapkan strategi coba lagi eksponensial. Alur kerja menggunakan aktivitas `unreliableActivity` yang sama sebagai alur kerja `DecoratorRetryWorkflow`yang dibahas sebelumnya. Antarmuka alur kerja diimplementasikan dalam `RetryWorkflow` dan memiliki satu metode, `process`, yang merupakan titik masuk alur kerja. Pekerja alur kerja diimplementasikan dalam `AsyncExecutorRetryWorkflowImpl`, sebagai berikut: 

```
public class AsyncExecutorRetryWorkflowImpl implements RetryWorkflow {
  private final RetryActivitiesClient client = new RetryActivitiesClientImpl();
  private final DecisionContextProvider contextProvider = new DecisionContextProviderImpl();
  private final WorkflowClock clock = contextProvider.getDecisionContext().getWorkflowClock();

  public void process() {
      long initialRetryIntervalSeconds = 5;
      int maximumAttempts = 5;
      handleUnreliableActivity(initialRetryIntervalSeconds, maximumAttempts);
  }
  public void handleUnreliableActivity(long initialRetryIntervalSeconds, int maximumAttempts) {

      ExponentialRetryPolicy retryPolicy = new ExponentialRetryPolicy(initialRetryIntervalSeconds).withMaximumAttempts(maximumAttempts);
      final AsyncExecutor executor = new AsyncRetryingExecutor(retryPolicy, clock);

      new TryCatch() {
          @Override
          protected void doTry() throws Throwable {
              executor.execute(new AsyncRunnable() {
                  @Override
                  public void run() throws Throwable {
                      client.unreliableActivity();
                  }
              });
          }
          @Override
          protected void doCatch(Throwable e) throws Throwable {
          }
      };
  }
}
```

Alur kerja bekerja sebagai berikut: 

1. `process` memanggil metode `handleUnreliableActivity` dan meneruskannya pengaturan konfigurasi.

1. `handleUnreliableActivity` menggunakan pengaturan konfigurasi dari Langkah 1 untuk membuat objek `ExponentialRetryPolicy`, `retryPolicy`.

1. `handleUnreliableActivity` membuat objek `AsyncRetryExecutor`, `executor`, dan meneruskan objek `ExponentialRetryPolicy` dari Langkah 2 dan sebuah instans dari jam alur kerja ke konstruktor

1.  `handleUnreliableActivity` mengimplementasikan sebuah kelas `TryCatch` bersarang anonim dan menimpa `doTry` dan metode `doCatch` untuk menjalankan upaya coba lagi dan menangani pengecualian apapun.

1. `doTry` membuat kelas `AsyncRunnable` anonim dan menimpa metode `run` untuk menerapkan kode kustom untuk mengeksekusi `unreliableActivity`. Untuk kesederhanaan, `run` hanya mengeksekusi aktivitas, tetapi Anda dapat menerapkan pendekatan yang lebih canggih yang sesuai.

1. `doTry` memanggil `executor.execute` dan meneruskannya objek `AsyncRunnable`. `execute` memanggil metode `AsyncRunnable` objek `run` untuk menjalankan aktivitas.

1. Jika aktivitas gagal, pelaksana memanggil `run` lagi, menurut konfigurasi objek `retryPolicy`. 

Untuk diskusi lebih lanjut tentang cara menggunakan kelas `TryCatch` untuk menangani kesalahan, lihat [AWS Flow Framework untuk Pengecualian Java](errorhandling.exceptions.md). 

## Strategi Coba Lagi Kustom
<a name="custom-retry-strategy"></a>

Pendekatan yang paling fleksibel untuk mencoba kembali aktivitas yang gagal adalah strategi khusus, yang secara rekursif memanggil metode asinkron yang menjalankan upaya coba lagi, seperti strategi. retry-until-success Namun, bukan hanya menjalankan aktivitas lagi, Anda menerapkan logika kustom yang memutuskan apakah dan cara menjalankan setiap upaya coba lagi berturut-turut. Pola dasar adalah: 

1. Buat objek status `Settable<T>`, yang digunakan untuk menunjukkan apakah aktivitas gagal.

1. Menerapkan sebuah `TryCatch` bersarang atau kelas `TryCatchFinally`.

1. `doTry` mengeksekusi aktivitas.

1. Jika aktivitasnya gagal, `doCatch` menetapkan objek status untuk menunjukkan bahwa aktivitas gagal.

1. Memanggil metode penanganan kegagalan asinkron dan menyebarkannya objek status. Metode menunda eksekusi sampai `TryCatch` atau `TryCatchFinally` selesai.

1. Metode penanganan kegagalan memutuskan apakah akan mencoba kembali aktivitas, dan jika demikian, kapan.

Alur kerja berikut menunjukkan cara menerapkan strategi coba lagi kustom. Alur kerja menggunakan aktivitas `unreliableActivity` yang sama sebagai `DecoratorRetryWorkflow` dan alur kerja `AsyncExecutorRetryWorkflow`. Antarmuka alur kerja diimplementasikan dalam `RetryWorkflow` dan memiliki satu metode, `process`, yang merupakan titik masuk alur kerja. Pekerja alur kerja diimplementasikan dalam `CustomLogicRetryWorkflowImpl`, sebagai berikut: 

```
public class CustomLogicRetryWorkflowImpl implements RetryWorkflow {
  ...
  public void process() {
      callActivityWithRetry();
  }
  @Asynchronous
  public void callActivityWithRetry() {
      final Settable<Throwable> failure = new Settable<Throwable>();
      new TryCatchFinally() {
          protected void doTry() throws Throwable {
              client.unreliableActivity();
          }
          protected void doCatch(Throwable e) {
              failure.set(e);
          }
          protected void doFinally() throws Throwable {
              if (!failure.isReady()) {
                  failure.set(null);
              }
          }
      };
      retryOnFailure(failure);
  }
  @Asynchronous
  private void retryOnFailure(Promise<Throwable> failureP) {
      Throwable failure = failureP.get();
      if (failure != null && shouldRetry(failure)) {
          callActivityWithRetry();
      }
  }
  protected Boolean shouldRetry(Throwable e) {
      //custom logic to decide to retry the activity or not
      return true;
  }
}
```

Alur kerja bekerja sebagai berikut:

1. `process` memanggil metode `callActivityWithRetry` asinkron.

1. `callActivityWithRetry` membuat objek `Settable<Throwable>` bernama gagal yang digunakan untuk menunjukkan apakah aktivitas telah gagal. `Settable<T>` berasal dari `Promise<T>` dan banyak bekerja dengan cara yang sama, tetapi Anda menetapkan nilai objek `Settable<T>` secara manual.

1. `callActivityWithRetry` mengimplementasikan sebuah kelas `TryCatchFinally` bersarang anonim untuk menangani pengecualian yang dilemparkan oleh `unreliableActivity`. Untuk diskusi lebih lanjut tentang cara menangani pengecualian dilemparkan oleh kode asinkron, lihat [AWS Flow Framework untuk Pengecualian Java](errorhandling.exceptions.md).

1. `doTry` mengeksekusi `unreliableActivity`.

1. Jika `unreliableActivity` melempar pengecualian, kerangka kerja memanggil `doCatch` dan meneruskannya objek pengecualian. `doCatch` mengatur `failure` ke objek pengecualian, yang menunjukkan bahwa aktivitas gagal dan menempatkan objek dalam status siap.

1. `doFinally` memeriksa apakah `failure` sudah siap, yang akan benar hanya jika `failure` telah ditetapkan oleh `doCatch`.
   + Jika `failure` sudah siap, `doFinally` tidak melakukan apa-apa.
   + Jika `failure` belum siap, aktivitas selesai dan `doFinally` menetapkan gagal ke `null`. 

1. `callActivityWithRetry` memanggil metode `retryOnFailure` asinkron dan meneruskannya dengan gagal. Karena gagal adalah jenis `Settable<T>`, `callActivityWithRetry` menunda eksekusi sampai gagal siap, yang terjadi setelah `TryCatchFinally` selesai.

1. `retryOnFailure` mendapat nilai dari gagal.
   + Jika gagal diatur ke nol, upaya coba lagi berhasil. `retryOnFailure` tidak melakukan apa-apa, yang mengakhiri proses coba lagi.
   + Jika gagal diatur ke objek pengecualian dan `shouldRetry` mengembalikan BETUL, `retryOnFailure` memanggil `callActivityWithRetry` untuk mencoba kembali aktivitas. 

     `shouldRetry` mengimplementasikan logika kustom untuk memutuskan apakah akan mencoba lagi aktivitas gagal. Untuk kesederhanaan, `shouldRetry` selalu mengembalikan `true` dan `retryOnFailure` mengeksekusi aktivitas segera, tetapi Anda dapat menerapkan logika yang lebih canggih sesuai kebutuhan. 

1. Langkah 2-8 ulangi hingga `unreliableActivity` melengkapi atau `shouldRetry` memutuskan untuk menghentikan proses. 

**catatan**  
`doCatch` tidak menangani proses coba lagi; itu hanya menetapkan gagal untuk menunjukkan bahwa aktivitas gagal. Proses coba lagi ditangani oleh metode `retryOnFailure` asinkron, yang menunda eksekusi sampai `TryCatch` selesai. Alasan untuk pendekatan ini adalah bahwa, jika Anda mencoba kembali aktivitas di `doCatch`, Anda tidak dapat membatalkannya. Mencoba kembali aktivitas di `retryOnFailure` mengizinkan Anda untuk melaksanakan kegiatan yang dapat dibatalkan. 