Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.

Mencoba lagi fungsi asinkron

Dokumen ini menjelaskan cara meminta fungsi latar belakang asinkron (non-HTTPS) yang akan dicoba ulang saat terjadi kegagalan.

Semantik percobaan ulang

Cloud Functions menjamin setidaknya sekali eksekusi fungsi berdasarkan peristiwa untuk setiap peristiwa yang dikeluarkan oleh sumber peristiwa. Namun, secara default, jika pemanggilan fungsi berhenti dengan pesan error, fungsi tersebut tidak akan dipanggil lagi, dan peristiwa akan dibatalkan. Saat Anda mengaktifkan percobaan ulang pada fungsi berdasarkan peristiwa, Cloud Functions akan mencoba kembali pemanggilan fungsi yang gagal hingga berhasil diselesaikan, atau jendela percobaan ulang (secara default, 7 hari) berakhir.

Alasan fungsi berdasarkan peristiwa gagal diselesaikan

Terkadang, fungsi keluar sebelum waktunya karena terjadi error internal, dan secara default fungsi tersebut akan atau tidak akan dicoba ulang secara otomatis.

Biasanya, fungsi berdasarkan peristiwa mungkin gagal diselesaikan karena terjadi error pada kode fungsi itu sendiri. Beberapa penyebabnya adalah sebagai berikut:

  • Fungsi berisi bug dan runtime menampilkan pengecualian.
  • Fungsi tidak dapat menjangkau endpoint layanan, atau waktu habis saat mencoba menjangkau endpoint.
  • Fungsi sengaja menampilkan pengecualian (misalnya, saat parameter menggagalkan validasi).
  • Jika fungsi yang ditulis dalam Node.js menampilkan promise yang ditolak atau meneruskan nilai bukan null ke callback.

Dalam kasus di atas, secara default fungsi akan berhenti dijalankan dan peristiwa itu akan dihapus. Jika ingin mencoba ulang fungsi ini ketika terjadi error, Anda dapat mengubah kebijakan percobaan ulang default dengan menyetel properti "coba ulang jika gagal". Dengan mengambil langkah ini, peristiwa akan dicoba ulang berkali-kali hingga beberapa hari sampai fungsi tersebut berhasil diselesaikan.

Mengaktifkan dan menonaktifkan percobaan ulang

Menggunakan Konsol GCP

Anda dapat mengaktifkan atau menonaktifkan percobaan ulang di Konsol GCP sebagai berikut:

  1. Buka halaman Ringkasan Cloud Functions di Cloud Platform Console.

  2. Klik Buat fungsi. Atau, klik fungsi yang ada untuk membuka halaman detailnya dan klik Edit.

  3. Lengkapi kolom wajib isi untuk fungsi Anda.

  4. Pastikan kolom Pemicu disetel ke jenis pemicu berdasarkan peristiwa, seperti Cloud Pub/Sub atau Cloud Storage.

  5. Perluas setelan lanjutan dengan mengklik Lainnya.

  6. Centang atau hapus centang pada kotak dengan label Coba lagi jika gagal.

Dalam kode fungsi

Dengan Cloud Functions for Firebase, Anda dapat mengaktifkan percobaan ulang dalam kode untuk suatu fungsi. Untuk melakukannya pada fungsi latar belakang seperti functions.foo.onBar(myHandler);, gunakan runWith dan konfigurasikan kebijakan kegagalan:

functions.runWith({failurePolicy: true}).foo.onBar(myHandler);

Menyetel true seperti yang ditampilkan akan mengonfigurasi fungsi untuk mencoba lagi jika gagal.

Praktik terbaik

Bagian ini menjelaskan praktik terbaik untuk menggunakan percobaan ulang.

Gunakan percobaan ulang untuk menangani error sementara

Karena fungsi terus dicoba ulang hingga berhasil dijalankan, error permanen, seperti bug, harus dihilangkan dari pengujian menyeluruh kode Anda sebelum percobaan ulang diaktifkan. Percobaan ulang paling baik digunakan untuk menangani kegagalan yang terputus-putus/sementara yang sangat mungkin akan teratasi melalui percobaan ulang, seperti endpoint layanan yang tidak stabil atau waktu tunggu habis.

Menetapkan kondisi akhir agar percobaan ulang tidak terjebak dalam loop tanpa henti

Salah satu praktik terbaik adalah melindungi fungsi Anda dari loop terus-menerus saat menggunakan percobaan ulang. Anda dapat melakukannya dengan menyertakan kondisi akhir yang ditetapkan dengan baik, sebelum fungsi mulai diproses. Ingat bahwa teknik ini hanya berfungsi jika fungsi Anda berhasil dimulai dan dapat mengevaluasi kondisi akhir.

Pendekatan yang sederhana tetapi efektif adalah dengan menghapus peristiwa yang memiliki stempel waktu lebih lama dari rentang tertentu. Langkah ini dapat menghindari eksekusi berlebihan saat kegagalan terus-menerus terjadi atau berlangsung lebih lama daripada perkiraan.

Misalnya, cuplikan kode ini menghapus semua peristiwa yang lebih lama dari 10 detik:

const eventAgeMs = Date.now() - Date.parse(event.timestamp);
const eventMaxAgeMs = 10000;
if (eventAgeMs > eventMaxAgeMs) {
  console.log(`Dropping event ${event} with age[ms]: ${eventAgeMs}`);
  callback();
  return;
}

Menggunakan catch dengan Promise

Jika fungsi Anda mengaktifkan percobaan ulang, error yang tidak ditangani akan memicu percobaan ulang. Pastikan kode Anda menangkap error yang seharusnya tidak menyebabkan percobaan ulang.

Berikut adalah contoh tindakan yang sebaiknya Anda lakukan:

return doFooAsync().catch((err) => {
    if (isFatal(err)) {
        console.error(`Fatal error ${err}`);
    }
    return Promise.reject(err);
});

Jadikan fungsi berdasarkan peristiwa yang dapat dicoba ulang menjadi bersifat idempoten

Fungsi berdasarkan peristiwa yang dapat dicoba lagi harus bersifat idempoten. Berikut adalah beberapa panduan umum untuk membuat fungsi bersifat idempoten:

  • Banyak API eksternal (seperti Stripe) yang dapat Anda gunakan untuk menyuplai kunci idempotensi sebagai parameter. Jika menggunakan API seperti itu, Anda harus menggunakan ID peristiwa sebagai kunci idempotensi.
  • Idempotensi berfungsi dengan baik pada pengiriman "setidaknya sekali" karena memberikan keamanan untuk mencoba ulang. Jadi, salah satu praktik terbaik yang umum untuk menulis kode tepercaya adalah dengan menggabungkan idempotensi dengan percobaan ulang.
  • Pastikan kode Anda idempoten secara internal. Contoh:
    • Pastikan mutasi bisa terjadi lebih dari sekali tanpa mengubah hasilnya.
    • Jalankan kueri pada status database dalam transaksi sebelum memutasikan status tersebut.
    • Pastikan semua efek samping bersifat idempoten.
  • Lakukan pemeriksaan transaksi di luar fungsi, terlepas dari kode. Sebagai contoh, pertahankan status di suatu tempat yang mencatat bahwa ID peristiwa tertentu telah diproses.
  • Tangani panggilan fungsi duplikat yang tidak umum. Misalnya, jalankan proses pembersihan terpisah yang akan melakukan pembersihan setelah panggilan fungsi duplikat.