Timeout, retry, SLA

Merancang kebijakan kegagalan per task: timeout, retry dengan backoff, dan SLA.

Daftar isi

Task dapat gagal karena sebab yang sementara, seperti jaringan yang terputus atau sumber data yang belum siap, maupun sebab yang tetap, seperti konfigurasi yang salah. Kebijakan kegagalan per task menentukan seberapa lama satu percobaan boleh berjalan, berapa kali kegagalan boleh dicoba ulang, dan apa yang dilakukan setelah seluruh percobaan habis. Topik ini membahas parameter percobaan ulang beserta jeda tunggu antar percobaannya, batas durasi execution_timeout, on_failure_callback, serta status fitur SLA (service level agreement) pada Airflow 3 beserta penggantinya.

Percobaan ulang dengan retries#

Parameter retries menyatakan jumlah percobaan ulang sebelum task dinyatakan gagal final, sedangkan retry_delay menyatakan jeda di antara percobaannya. Task yang gagal tidak langsung berstatus failed, melainkan up_for_retry, lalu dijadwalkan kembali setelah jeda tersebut. Apabila seluruh percobaan habis dan task tetap gagal, statusnya menjadi failed dan task hilirnya tidak dijadwalkan.

Dua parameter pelengkap mengatur sisi lain kegagalan. AirflowFailException menggagalkan task langsung tanpa menjalankan sisa percobaan ulang, sehingga cocok untuk kegagalan yang tidak mungkin pulih. on_failure_callback memanggil fungsi tertentu setelah percobaan terakhir berakhir gagal.

DAG berikut memuat task yang sengaja dibuat gagal pada percobaan pertamanya. Agar percobaan berikutnya berbeda perilakunya, task menulis berkas penanda di /tmp/ra-timeout-retry-sla. Percobaan pertama membuat berkas penanda itu lalu melempar ValueError, sedangkan percobaan berikutnya menemukan berkas penanda yang sama dan berhasil.

python dag_coba_ulang.py
"""DAG yang gagal sekali lalu berhasil setelah percobaan ulang."""
from datetime import timedelta
from pathlib import Path
from airflow.sdk import dag, task

PENANDA = Path("/tmp/ra-timeout-retry-sla/penanda.txt")


@dag(
    dag_id="coba_ulang",
    schedule=None,
    description="Task yang gagal pada percobaan pertama lalu sukses setelah retry.",
)
def coba_ulang():
    @task(retries=2, retry_delay=timedelta(seconds=1))
    def rapikan_arsip() -> str:
        """Gagal pada percobaan pertama, sukses pada percobaan berikutnya."""
        if not PENANDA.exists():
            PENANDA.parent.mkdir(parents=True, exist_ok=True)
            PENANDA.write_text("percobaan pertama sudah berjalan")
            raise ValueError("folder kerja belum siap, gagal untuk latihan retry")
        return "folder kerja siap"

    @task
    def lanjutkan(status: str) -> None:
        """Berjalan setelah task sebelumnya berhasil."""
        print(f"status: {status}")

    lanjutkan(rapikan_arsip())


dag = coba_ulang()

Argumen retries=2 menghasilkan total tiga kali eksekusi, yaitu satu percobaan awal dan dua percobaan ulang, dengan jeda satu detik di antaranya. Kehadiran task lanjutkan menunjukkan bahwa task hilir tetap berjalan setelah rapikan_arsip pulih dari kegagalan pertamanya.

bash
# lingkungan latihan terpisah untuk topik ini
export AIRFLOW_HOME=/tmp/ra-timeout-retry-sla
export AIRFLOW__CORE__LOAD_EXAMPLES=False
bash
# uji bahwa berkas DAG dapat diparse tanpa keluaran apa pun
python3 dag_coba_ulang.py
bash
# siapkan folder dags lalu salin berkas DAG ke dalamnya
mkdir -p "$AIRFLOW_HOME/dags"
cp dag_coba_ulang.py "$AIRFLOW_HOME/dags/"
bash
# siapkan skema basis data metadata
# log migrasi berisi stempel waktu, sehingga tidak ditampilkan
airflow db migrate > /dev/null 2>&1
bash
# hapus berkas penanda agar percobaan pertama gagal sesuai rancangan
rm -f /tmp/ra-timeout-retry-sla/penanda.txt
bash
# jalankan seluruh task DAG sekali secara lokal
airflow dags test coba_ulang 2026-11-04 > /tmp/ra-timeout-retry-sla/coba-ulang.log 2>&1

Keluaran perintah terakhir panjang dan bertanda waktu, sehingga tidak ditampilkan. Pada log, percobaan pertama rapikan_arsip berakhir dengan baris ValueError: folder kerja belum siap, gagal untuk latihan retry, kemudian status task berubah menjadi up_for_retry. Setelah jeda satu detik, percobaan kedua menemukan berkas penanda dan mengembalikan folder kerja siap. Task lanjutkan kemudian mencetak status: folder kerja siap, lalu dag run ditutup dengan status success. Kegagalan pertama tidak menghentikan dag run karena retries masih menyisakan percobaan ulang, sedangkan kegagalan yang sama pada kedua percobaan berikutnya justru akan menutup dag run dengan status failed.

Jeda tunggu dengan backoff eksponensial#

Jeda tetap antar percobaan cocok untuk pemulihan cepat, tetapi sumber yang mengalami gangguan panjang lebih baik diperiksa dengan jeda yang makin lama makin jarang. Pola jeda yang berlipat seperti ini disebut backoff eksponensial, dan Airflow mengaktifkannya melalui parameter retry_exponential_backoff=True. Parameter tersebut menggandakan jeda retry_delay pada setiap percobaan ulang, sedangkan max_retry_delay menetapkan batas atasnya. Perhitungan berikut menggambarkan jeda untuk nilai retry_delay 30 detik dan max_retry_delay 120 detik.

python Contoh: perhitungan jeda backoff eksponensial
def jeda_backoff(dasar: int, percobaan: int, maksimum: int) -> int:
    """Menghitung jeda tunggu percobaan ulang ke-percobaan."""
    faktor = 2 ** (percobaan - 1)
    return min(faktor * dasar, maksimum)

DASAR = 30
MAKSIMUM = 120

for percobaan in (1, 2, 3, 4):
    print(f"percobaan ke-{percobaan}: jeda {jeda_backoff(DASAR, percobaan, MAKSIMUM)} detik")
text Keluaran
percobaan ke-1: jeda 30 detik
percobaan ke-2: jeda 60 detik
percobaan ke-3: jeda 120 detik
percobaan ke-4: jeda 120 detik

Jeda pada keluaran memperlihatkan pola penggandaan 30, 60, 120 detik yang berhenti di batas max_retry_delay, sehingga percobaan keempat dan seterusnya tetap menunggu 120 detik. Pada DAG coba_ulang, jeda antar percobaan tetap satu detik karena backoff tidak diaktifkan. Perhitungan di atas berlaku ketika retry_exponential_backoff=True. Backoff eksponensial cocok untuk sumber data yang pulih dalam hitungan menit, karena pemeriksaan tiap detik hanya menghabiskan percobaan tanpa hasil.

Batas durasi dengan execution_timeout#

Parameter execution_timeout menetapkan batas durasi satu percobaan task. Parameter ini melengkapi percobaan ulang pada kasus task yang menggantung, karena task seperti itu tidak pernah selesai dan tidak pernah berstatus gagal dengan sendirinya. Apabila batas terlewati, percobaan dihentikan dengan error AirflowTaskTimeout, dan percobaan ulang tetap berlaku untuk kegagalan tersebut sebagaimana kegagalan lainnya.

DAG berikut memuat satu task yang menunda eksekusi selama dua detik pada percobaan pertamanya, padahal batas durasinya satu detik. Percobaan kedua yang berjalan cepat berhasil menutup dag run.

python dag_batas_waktu.py
"""DAG dengan task yang melewati execution_timeout pada percobaan pertama."""
import time
from datetime import timedelta
from pathlib import Path
from airflow.sdk import dag, task

PENANDA = Path("/tmp/ra-timeout-retry-sla/batas.txt")


@dag(
    dag_id="batas_waktu",
    schedule=None,
    description="Task yang gagal karena melewati execution_timeout lalu sukses setelah retry.",
)
def batas_waktu():
    @task(execution_timeout=timedelta(seconds=1), retries=1, retry_delay=timedelta(seconds=1))
    def analisis_lama() -> None:
        """Berhenti terlalu lama pada percobaan pertama, cepat pada percobaan kedua."""
        if not PENANDA.exists():
            PENANDA.parent.mkdir(parents=True, exist_ok=True)
            PENANDA.write_text("percobaan pertama berjalan terlalu lama")
            time.sleep(2)
        print("analisis selesai tepat waktu")

    analisis_lama()


dag = batas_waktu()
bash
# uji bahwa berkas DAG kedua dapat diparse tanpa keluaran apa pun
python3 dag_batas_waktu.py
bash
# salin berkas DAG kedua ke folder dags bila ingin dijalankan
cp dag_batas_waktu.py "$AIRFLOW_HOME/dags/"

Apabila DAG ini dijalankan, urutan eksekusinya sama dengan latihan retry sebelumnya. Percobaan pertama dihentikan dengan error AirflowTaskTimeout setelah batas satu detik terlewati. Status task berubah menjadi up_for_retry karena retries=1, kemudian percobaan kedua mencetak analisis selesai tepat waktu dan menutup dag run dengan status success. DAG ini hanya diparse pada topik ini dan tidak dijalankan dengan airflow dags test, karena menjalankan skenario ini hanya menambah jeda tunggu tanpa menambah pemahaman.

SLA pada Airflow 3#

Airflow 2 menyediakan fitur SLA, yaitu batas waktu penyelesaian task yang diukur terhadap jadwalnya, lengkap dengan pencatatan pelanggaran serta callback khusus berupa fungsi yang dijalankan Airflow pada peristiwa tertentu. Fitur tersebut tidak lagi ada pada Airflow 3.0. Catatan rilis versi 3.0 menyatakan bahwa fitur SLA lama, termasuk callback dan metriknya, telah dihapus, sehingga parameter sla pada task tidak perlu dicari lagi.

Penggantinya adalah Deadline Alerts yang diperkenalkan pada Airflow 3.1. Mekanisme ini menetapkan ambang waktu terhadap dag run, misalnya dag run yang belum selesai 30 menit setelah masuk antrean. Ketika ambang terlampaui, fitur ini menjalankan callback atau notifier, yaitu komponen pengirim pemberitahuan yang dipilih penulis DAG. Fitur ini masih berstatus experimental, yakni bentuk dan parameternya dapat berubah antar versi tanpa pemberitahuan.

Untuk kebutuhan yang lebih sederhana, dokumentasi mengarahkan pada dua alternatif, yaitu pemberitahuan kustom melalui hook sukses dan gagal di tingkat task, serta integrasi dengan sistem monitoring eksternal. Notifikasi sederhana dapat ditangani dengan on_failure_callback pada task, sedangkan pengawasan durasi yang lebih lengkap didelegasikan ke sistem monitoring eksternal.

Kesalahan umum#

Mengaktifkan retries pada kegagalan yang tidak sementara. Setiap percobaan mengulang error yang sama, sehingga dag run tertunda tanpa hasil sebelum seluruh percobaan habis. Simpan retries untuk kegagalan yang membaik seiring waktu, dan gunakan AirflowFailException untuk menggagalkan task segera.

Menetapkan execution_timeout di bawah durasi normal task. Task yang berjalan normal pun ikut dihentikan oleh batas tersebut. Ukur durasi normal task terlebih dahulu, lalu beri margin yang jelas di atas durasi tersebut.

Mencari parameter sla pada Airflow 3. Parameter sla sudah dihapus bersama fitur SLA lama pada versi 3.0. Gunakan Deadline Alerts atau alternatif pemberitahuan lainnya sesuai kebutuhan pengawasannya.

Ringkasan#

  • retries dan retry_delay mengatur percobaan ulang, dengan status up_for_retry di antara percobaan dan status failed setelah seluruh percobaan habis.
  • retry_exponential_backoff menggandakan jeda antar percobaan hingga batas max_retry_delay.
  • execution_timeout menghentikan percobaan yang melewati batas durasinya dengan error AirflowTaskTimeout, dan on_failure_callback dipanggil setelah percobaan terakhir berakhir gagal.
  • Fitur SLA lama dihapus pada Airflow 3.0 dan digantikan Deadline Alerts pada versi 3.1 yang masih berstatus experimental.

Referensi#