Task failure callbacks in Apache Airflow - Time & Space Complexity
When Airflow runs tasks, it can call special functions if a task fails. Understanding how often these callbacks run helps us see how the system behaves as tasks increase.
We want to know how the work done by failure callbacks grows as the number of tasks grows.
Analyze the time complexity of the following Airflow DAG snippet with failure callbacks.
from airflow import DAG
from airflow.operators.python import PythonOperator
from datetime import datetime
def on_failure_callback(context):
print(f"Task {context['task_instance'].task_id} failed.")
def task_function():
pass
dag = DAG('example_failure_callback', start_date=datetime(2024, 1, 1))
task1 = PythonOperator(
task_id='task1',
python_callable=task_function,
on_failure_callback=on_failure_callback,
dag=dag
)
task2 = PythonOperator(
task_id='task2',
python_callable=task_function,
on_failure_callback=on_failure_callback,
dag=dag
)
This code sets up two tasks in a DAG, each with a failure callback that runs if the task fails.
Look at what repeats when tasks run and fail.
- Primary operation: The failure callback function runs once per failed task.
- How many times: At most once per task failure, so up to the number of tasks.
As the number of tasks increases, the number of failure callbacks that might run grows in a straight line.
| Input Size (n tasks) | Approx. Failure Callback Runs |
|---|---|
| 10 | Up to 10 |
| 100 | Up to 100 |
| 1000 | Up to 1000 |
Pattern observation: The number of failure callbacks grows directly with the number of tasks.
Time Complexity: O(n)
This means the work done by failure callbacks grows linearly with the number of tasks that fail.
[X] Wrong: "Failure callbacks run once for the whole DAG regardless of how many tasks fail."
[OK] Correct: Each task can fail independently, so each failure triggers its own callback. The callbacks add up with more failing tasks.
Knowing how failure callbacks scale helps you design reliable workflows. It shows you how extra work grows as your DAG grows, which is useful for real projects and discussions.
"What if the failure callback triggers another task that also has a failure callback? How would the time complexity change?"
Practice
on_failure_callback in an Airflow task?Solution
Step 1: Understand the role of
This parameter is designed to specify a function that runs automatically when a task fails.on_failure_callbackStep 2: Differentiate from other task features
Scheduling and retries are handled by other parameters, noton_failure_callback.Final Answer:
To run a function automatically when the task fails -> Option AQuick Check:
Failure callback = automatic function on failure [OK]
- Confusing failure callback with scheduling
- Thinking it retries the task automatically
- Assuming it runs on task success
notify_failure to an Airflow task?Solution
Step 1: Recall the exact parameter name
The correct parameter to assign a failure callback ison_failure_callback.Step 2: Match the parameter with the options
Only task = PythonOperator(on_failure_callback=notify_failure, ...) useson_failure_callbackcorrectly.Final Answer:
task = PythonOperator(on_failure_callback=notify_failure, ...) -> Option BQuick Check:
Correct parameter name = on_failure_callback [OK]
- Using incorrect parameter names like failure_callback
- Swapping words in the parameter name
- Misspelling the parameter
def alert(context):
print(f"Task {context['task_instance'].task_id} failed")
task = PythonOperator(
task_id='my_task',
python_callable=lambda: 1/0,
on_failure_callback=alert
)Solution
Step 1: Analyze the task's python_callable
The lambda divides 1 by 0, causing a failure (ZeroDivisionError).Step 2: Understand the failure callback behavior
On failure, thealertfunction runs and prints the failure message with the task ID.Final Answer:
Task my_task failed -> Option DQuick Check:
Failure triggers alert print [OK]
- Expecting ZeroDivisionError to print directly
- Thinking task succeeds despite error
- Ignoring the callback print output
def fail_alert():
print("Task failed")
task = PythonOperator(
task_id='fail_task',
python_callable=lambda: 1/0,
on_failure_callback=fail_alert
)Why does the callback not run when the task fails?
Solution
Step 1: Check callback function signature
Failure callbacks receive a context dictionary argument; missing it causes errors.Step 2: Understand Airflow callback requirements
The callback must accept one parameter (context) to work properly.Final Answer:
The callback function must accept a context parameter -> Option CQuick Check:
Callback needs context argument [OK]
- Defining callback without parameters
- Expecting return value from callback
- Making callback async unnecessarily
on_failure_callback function?Solution
Step 1: Understand the requirement
Send email only if failure reason contains "timeout".Step 2: Use context to check exception message
The failure callback receives context with exception info; check if 'timeout' is in the exception string.Step 3: Send email conditionally
Send email alert only if the condition is met inside the callback function.Final Answer:
Define a function that checkscontext['exception']for 'timeout' and sends email if true -> Option AQuick Check:
Check exception text in callback before alert [OK]
- Sending email on all failures without filtering
- Trying to retry task in failure callback
- Ignoring exception details in context
Ready to prove it?
Pass the test and this pattern moves unknown
