Skip to content

Deferred TI's next_method and next_kwargs not cleared on retries #18146

Closed

Description

@jedcunningham

Apache Airflow version

main (development)

Operating System

macOS 11.5.2

Versions of Apache Airflow Providers

No response

Deployment

Virtualenv installation

Deployment details

No response

What happened

If your first try fails and you have retries enabled, the subsequent tries skip right to the final next_method(**next_kwargs) instead of starting with execute again.

What you expected to happen

Like we reset things like start date, we should wipe next_method and next_kwargs so we can retry the task from the beginning.

How to reproduce

No response

Anything else

No response

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Code of Conduct

Activity

  1. added this to the Airflow 2.2 milestone on Sep 10, 2021
  2. changed the title [-]Deferrable operator not clearing `next_method` and `next_kwargs` on retries[/-] [+]Deferred TI's `next_method` and `next_kwargs` not cleared on retries[/+] on Sep 10, 2021
  3. added a commit that references this issue on Sep 13, 2021
    c93beb5
  4. added a commit that references this issue on Sep 13, 2021
    9d49772
  5. jedcunningham commented on Sep 13, 2021

    @jedcunningham
    MemberAuthor

    The following DAG can be used to both reproduce (dagruns fail) and verify the issue is fixed (dagruns succeed). Basically, the first run it will fail so it ends up in UP_FOR_RETRY and will succeed on the second try.

    from datetime import datetime, timedelta
    
    from airflow import DAG
    from airflow.exceptions import AirflowException
    from airflow.models import BaseOperator
    from airflow.triggers.testing import SuccessTrigger
    
    
    class RetryOperator(BaseOperator):
        def execute(self, context):
            ti = context["ti"]
            has_next_method = bool(ti.next_method)
            try_number = ti.try_number
            self.log.info(
                f"In `execute`: has_next_method: {has_next_method}, try_number:{try_number}"
            )
    
            self.defer(
                trigger=SuccessTrigger(),
                method_name="next",
                kwargs={"execute_try_number": try_number},
            )
    
        def next(self, context, execute_try_number, event=None):
            self.log.info("In next!")
            ti = context["ti"]
            has_next_method = bool(ti.next_method)
            try_number = ti.try_number
            self.log.info(
                f"In `next`: has_next_method: {has_next_method}, try_number:{try_number}, excute_try_number: {execute_try_number}"
            )
    
            if try_number == 1:
                # Force a retry
                raise AirflowException("Force a retry")
            # Did we run `execute`?
            if execute_try_number != try_number:
                raise AirflowException("`execute` wasn't run during retry!")
            return None  # Success!
    
    
    with DAG(
        "triggerer_retry", schedule_interval=None, start_date=datetime(2021, 9, 13)
    ) as dag:
        RetryOperator(task_id="retry", retries=1, retry_delay=timedelta(seconds=15))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions