This is an automated email from the ASF dual-hosted git repository.

ferruzzi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 637b741f1a6 Pass Dag runs directly to Deadline references (#70714)
637b741f1a6 is described below

commit 637b741f1a60f0a059dd60f2a62bd47c0e38cd54
Author: Richard <[email protected]>
AuthorDate: Thu Oct 15 10:48:26 2026 -0600

    Pass Dag runs directly to Deadline references (#70714)
    
    * Fix custom Deadline references with optional keyword arguments
    Preserve the Dag run evaluation context for custom references that accept
    additional keyword arguments, so they continue to evaluate correctly.
    
    Co-authored-by: D. Ferruzzi <[email protected]>
---
 airflow-core/docs/howto/deadline-alerts.rst        |  25 +-
 airflow-core/newsfragments/70714.significant.rst   |   1 +
 airflow-core/src/airflow/models/deadline.py        | 139 ++++-------
 airflow-core/src/airflow/models/taskinstance.py    |  25 +-
 .../src/airflow/serialization/definitions/dag.py   |   2 +-
 .../airflow/serialization/definitions/deadline.py  |  90 ++------
 airflow-core/tests/unit/models/test_deadline.py    | 257 ++++-----------------
 .../tests/unit/models/test_deadline_alert.py       |  84 ++++++-
 task-sdk/src/airflow/sdk/definitions/deadline.py   |  37 ++-
 9 files changed, 224 insertions(+), 436 deletions(-)

diff --git a/airflow-core/docs/howto/deadline-alerts.rst 
b/airflow-core/docs/howto/deadline-alerts.rst
index 76b18a99e45..538173c3505 100644
--- a/airflow-core/docs/howto/deadline-alerts.rst
+++ b/airflow-core/docs/howto/deadline-alerts.rst
@@ -466,9 +466,9 @@ Place the reference classes and the plugin that registers 
them in your plugins f
     class MyCustomDecoratedReference(BaseDeadlineReference):
         """A custom reference evaluated when Dag runs are created."""
 
-        def _evaluate_with(self, *, session: Session, **kwargs) -> datetime:
-            # Add your business logic here
-            return your_datetime
+        def _evaluate_with(self, *, session: Session, dagrun) -> datetime:
+            my_datetime = my_business_logic(dagrun.logical_date)
+            return my_datetime
 
 
     # You can specify when evaluate_with will be called by providing a 
DeadlineReference.TYPES value.
@@ -476,14 +476,9 @@ Place the reference classes and the plugin that registers 
them in your plugins f
     class MyQueuedReference(BaseDeadlineReference):
         """A custom reference evaluated when Dag runs are queued."""
 
-        # Ask for the Dag run context values supplied by Airflow; see notes 
below.
-        required_kwargs = {"dag_id", "run_id"}
-
-        def _evaluate_with(self, *, session: Session, **kwargs) -> datetime:
-            dag_id = kwargs["dag_id"]
-            run_id = kwargs["run_id"]
-            # Use dag_id and run_id in your calculation
-            return your_datetime
+        def _evaluate_with(self, *, session: Session, dagrun) -> datetime:
+            my_datetime = my_business_logic(dagrun.queued_at)
+            return my_datetime
 
 
     # Register the classes so the scheduler can resolve them when it 
deserializes the Dag.
@@ -564,8 +559,8 @@ followed by a more urgent escalation if the Dag is still 
running.
 * **Plugin Registration**: Custom references must be listed in the 
``deadline_references`` attribute
   of an ``AirflowPlugin``, so the plugins directory is the natural home for 
them.
 * **API Server Restart**: Restart the Airflow API Server after adding or 
modifying custom references.
-* **Required Parameters**: ``required_kwargs`` declares which Dag run context 
values Airflow should
-  forward to ``_evaluate_with()``. Only ``dag_id`` and ``run_id`` are 
available; declaring anything
-  else raises a ``ValueError`` when the deadline is evaluated. To configure a 
reference itself, give
-  it constructor fields or read from an Airflow Variable.
+* **Dag run context**: Add a ``dagrun`` parameter to ``_evaluate_with()`` to 
use the Dag run being evaluated.
+* **Required Parameters** *(deprecated)*: ``required_kwargs`` declares which 
parameters your reference
+  needs. It still works but is deprecated and will be removed in Airflow 4.0 — 
declare the keyword-only
+  parameters your ``_evaluate_with()`` needs instead.
 * **Database Access**: Use the ``session`` parameter for Airflow database 
queries if needed.
diff --git a/airflow-core/newsfragments/70714.significant.rst 
b/airflow-core/newsfragments/70714.significant.rst
new file mode 100644
index 00000000000..70572b6d598
--- /dev/null
+++ b/airflow-core/newsfragments/70714.significant.rst
@@ -0,0 +1 @@
+Deprecate the ``required_kwargs`` attribute for custom deadline references. 
Implement ``_evaluate_with()`` with a ``dagrun`` parameter instead.
diff --git a/airflow-core/src/airflow/models/deadline.py 
b/airflow-core/src/airflow/models/deadline.py
index 77e3c682e7b..b9c212dc834 100644
--- a/airflow-core/src/airflow/models/deadline.py
+++ b/airflow-core/src/airflow/models/deadline.py
@@ -17,21 +17,23 @@
 from __future__ import annotations
 
 import logging
+import warnings
 from abc import ABC, abstractmethod
 from collections.abc import Sequence
 from dataclasses import dataclass
 from datetime import datetime, timedelta
-from typing import TYPE_CHECKING, Any, cast
+from inspect import signature
+from typing import TYPE_CHECKING, Any, Protocol, cast
 from uuid import UUID
 
 import uuid6
-from sqlalchemy import Boolean, ForeignKey, Index, Integer, Uuid, and_, func, 
inspect, select, text
-from sqlalchemy.exc import SQLAlchemyError
+from sqlalchemy import Boolean, ForeignKey, Index, Integer, Uuid, and_, func, 
select, text
 from sqlalchemy.orm import Mapped, mapped_column, relationship
 
 from airflow._shared.observability.metrics import stats
 from airflow._shared.timezones import timezone
 from airflow.configuration import conf
+from airflow.exceptions import RemovedInAirflow4Warning
 from airflow.models.base import Base
 from airflow.models.callback import (
     Callback,
@@ -57,6 +59,38 @@ logger = logging.getLogger(__name__)
 CALLBACK_METRICS_PREFIX = "deadline_alerts"
 
 
+class DeadlineDagRunProtocol(Protocol):
+    """The Dag run interface deadline references are evaluated against."""
+
+    dag_id: str
+    logical_date: datetime | None
+    queued_at: datetime | None
+
+
+def _get_evaluation_kwargs(reference: Any, evaluator: Any, kwargs: dict[str, 
Any]) -> dict[str, Any]:
+    """Return the evaluation arguments accepted by a deadline reference."""
+    required_kwargs: set[str] | None = getattr(reference, "required_kwargs", 
None)
+    if required_kwargs is not None:
+        warnings.warn(
+            "required_kwargs is deprecated. Declare the keyword-only 
parameters your "
+            "_evaluate_with() implementation needs instead.",
+            RemovedInAirflow4Warning,
+            stacklevel=3,
+        )
+        kwargs = {key: value for key, value in kwargs.items() if key in 
required_kwargs}
+        if missing_kwargs := required_kwargs - kwargs.keys():
+            raise ValueError(
+                f"{reference.__class__.__name__} is missing required 
parameters: {', '.join(missing_kwargs)}"
+            )
+        return kwargs
+
+    parameters = signature(evaluator).parameters
+    if any(param.kind is param.VAR_KEYWORD for param in parameters.values()):
+        return kwargs
+
+    return {key: value for key, value in kwargs.items() if key in parameters}
+
+
 class classproperty:
     """
     Decorator that converts a method with a single cls argument into a 
property.
@@ -323,34 +357,18 @@ class ReferenceModels:
     class BaseDeadlineReference(LoggingMixin, ABC):
         """Base class for all Deadline implementations."""
 
-        # Set of required kwargs - subclasses should override this.
-        required_kwargs: set[str] = set()
-
         @classproperty
         def reference_name(cls: Any) -> str:
             return cls.__name__
 
         def evaluate_with(self, *, session: Session, interval: timedelta, 
**kwargs: Any) -> datetime | None:
-            """Validate the provided kwargs and evaluate this deadline with 
the given conditions."""
-            filtered_kwargs = {k: v for k, v in kwargs.items() if k in 
self.required_kwargs}
-
-            if missing_kwargs := self.required_kwargs - filtered_kwargs.keys():
-                raise ValueError(
-                    f"{self.__class__.__name__} is missing required 
parameters: {', '.join(missing_kwargs)}"
-                )
-
-            if extra_kwargs := kwargs.keys() - filtered_kwargs.keys():
-                self.log.debug(
-                    "%s ignoring unexpected parameters: %s",
-                    self.reference_name,
-                    ", ".join(extra_kwargs),
-                )
-
-            base_time = self._evaluate_with(session=session, **filtered_kwargs)
+            """Evaluate this deadline with the supplied context."""
+            evaluation_kwargs = _get_evaluation_kwargs(self, 
self._evaluate_with, kwargs)
+            base_time = self._evaluate_with(session=session, 
**evaluation_kwargs)
             return base_time + interval if base_time is not None else None
 
         @abstractmethod
-        def _evaluate_with(self, *, session: Session, **kwargs: Any) -> 
datetime | None:
+        def _evaluate_with(self, *, session: Session, dagrun: 
DeadlineDagRunProtocol) -> datetime | None:
             """Must be implemented by subclasses to perform the actual 
evaluation."""
             raise NotImplementedError
 
@@ -384,7 +402,7 @@ class ReferenceModels:
 
         _datetime: datetime
 
-        def _evaluate_with(self, *, session: Session, **kwargs: Any) -> 
datetime | None:
+        def _evaluate_with(self, *, session: Session, **kwargs) -> datetime | 
None:
             return self._datetime
 
         def serialize_reference(self) -> dict:
@@ -400,23 +418,14 @@ class ReferenceModels:
     class DagRunLogicalDateDeadline(BaseDeadlineReference):
         """A deadline that returns a DagRun's logical date."""
 
-        required_kwargs = {"dag_id", "run_id"}
-
-        def _evaluate_with(self, *, session: Session, **kwargs: Any) -> 
datetime | None:
-            from airflow.models import DagRun
-
-            return _fetch_from_db(DagRun.logical_date, session=session, 
**kwargs)
+        def _evaluate_with(self, *, session: Session, dagrun: 
DeadlineDagRunProtocol) -> datetime | None:
+            return dagrun.logical_date
 
     class DagRunQueuedAtDeadline(BaseDeadlineReference):
         """A deadline that returns when a DagRun was queued."""
 
-        required_kwargs = {"dag_id", "run_id"}
-
-        @provide_session
-        def _evaluate_with(self, *, session: Session, **kwargs: Any) -> 
datetime | None:
-            from airflow.models import DagRun
-
-            return _fetch_from_db(DagRun.queued_at, session=session, **kwargs)
+        def _evaluate_with(self, *, session: Session, dagrun: 
DeadlineDagRunProtocol) -> datetime | None:
+            return dagrun.queued_at
 
     @dataclass
     class AverageRuntimeDeadline(BaseDeadlineReference):
@@ -425,7 +434,6 @@ class ReferenceModels:
         DEFAULT_LIMIT = 10
         max_runs: int
         min_runs: int | None = None
-        required_kwargs = {"dag_id"}
 
         def __post_init__(self):
             if self.min_runs is None:
@@ -434,10 +442,10 @@ class ReferenceModels:
                 raise ValueError("min_runs must be at least 1")
 
         @provide_session
-        def _evaluate_with(self, *, session: Session, **kwargs: Any) -> 
datetime | None:
+        def _evaluate_with(self, *, session: Session, dagrun: 
DeadlineDagRunProtocol) -> datetime | None:
             from airflow.models import DagRun
 
-            dag_id = kwargs["dag_id"]
+            dag_id = dagrun.dag_id
 
             # Get database dialect to use appropriate time difference 
calculation
             dialect = get_dialect_name(session)
@@ -510,54 +518,3 @@ class ReferenceModels:
 
 
 DeadlineReferenceType = ReferenceModels.BaseDeadlineReference
-
-
-@provide_session
-def _fetch_from_db(model_reference: Mapped, *, session=None, **conditions) -> 
datetime | None:
-    """
-    Fetch a datetime value from the database using the provided model 
reference and filtering conditions.
-
-    For example, to fetch a TaskInstance's start_date:
-        _fetch_from_db(
-            TaskInstance.start_date, dag_id='example_dag', 
task_id='example_task', run_id='example_run'
-        )
-
-    This generates SQL equivalent to:
-        SELECT start_date
-        FROM task_instance
-        WHERE dag_id = 'example_dag'
-            AND task_id = 'example_task'
-            AND run_id = 'example_run'
-
-    :param model_reference: SQLAlchemy Column to select (e.g., 
DagRun.logical_date, TaskInstance.start_date)
-    :param conditions: Filtering conditions applied as equality comparisons in 
the WHERE clause.
-                       Multiple conditions are combined with AND.
-    :param session: SQLAlchemy session (auto-provided by decorator)
-    """
-    query = select(model_reference)
-
-    for key, value in conditions.items():
-        inspected = inspect(model_reference)
-        if inspected is not None:
-            query = query.where(getattr(inspected.class_, key) == value)
-
-    compiled_query = query.compile(compile_kwargs={"literal_binds": True})
-    pretty_query = "\n    ".join(str(compiled_query).splitlines())
-    logger.debug(
-        "Executing query:\n    %r\nAs SQL:\n    %s",
-        query,
-        pretty_query,
-    )
-
-    try:
-        result = session.scalar(query)
-    except SQLAlchemyError:
-        logger.exception("Database query failed.")
-        raise
-
-    if result is None:
-        message = f"No matching record found in the database for query:\n    
{pretty_query}"
-        logger.error(message)
-        raise ValueError(message)
-
-    return result
diff --git a/airflow-core/src/airflow/models/taskinstance.py 
b/airflow-core/src/airflow/models/taskinstance.py
index 8c3a811a17b..c90deef1b60 100644
--- a/airflow-core/src/airflow/models/taskinstance.py
+++ b/airflow-core/src/airflow/models/taskinstance.py
@@ -255,14 +255,11 @@ def _add_and_prime_mapped_ti(
     set_committed_value(ti, "dag_run", dag_run)
 
 
-def _recalculate_dagrun_queued_at_deadlines(
-    dagrun: DagRun, new_queued_at: datetime, session: Session
-) -> None:
+def _recalculate_dagrun_queued_at_deadlines(dagrun: DagRun, *, session: 
Session) -> None:
     """
     Recalculate deadline times for deadlines that reference dagrun.queued_at.
 
     :param dagrun: The DagRun whose deadlines should be recalculated
-    :param new_queued_at: The new queued_at timestamp to use for calculation
     :param session: Database session
 
     :meta private:
@@ -285,12 +282,9 @@ def _recalculate_dagrun_queued_at_deadlines(
     from airflow.serialization.decoders import decode_deadline_alert_model, 
resolve_deadline_alert_interval
 
     for deadline, deadline_alert in results:
-        # We can't use evaluate_with() since the new queued_at is not written 
to the DB yet, and
-        # interval is stored as JSON, so it has to be decoded rather than 
passed to timedelta().
         try:
-            interval = resolve_deadline_alert_interval(
-                decode_deadline_alert_model(deadline_alert), session=session
-            )
+            decoded_alert = decode_deadline_alert_model(deadline_alert)
+            interval = resolve_deadline_alert_interval(decoded_alert, 
session=session)
         except (ValueError, TypeError):
             # Either step can fail: the alert may hold a payload the decoder 
refuses, or a
             # variable-backed interval may point at a Variable that is missing 
or non-numeric.
@@ -304,7 +298,16 @@ def _recalculate_dagrun_queued_at_deadlines(
             )
             continue
 
-        new_deadline_time = new_queued_at + interval
+        new_deadline_time = decoded_alert.reference.evaluate_with(
+            session=session,
+            interval=interval,
+            dagrun=dagrun,
+            dag_id=dagrun.dag_id,
+            run_id=dagrun.run_id,
+        )
+
+        if new_deadline_time is None:
+            continue
 
         log.debug(
             "Recalculating deadline %s for DagRun %s.%s: old=%s, new=%s",
@@ -603,7 +606,7 @@ def clear_task_instances(
                     parent_context=parent_trace_context(dr.conf),
                 )
 
-                _recalculate_dagrun_queued_at_deadlines(dr, dr.queued_at, 
session)
+                _recalculate_dagrun_queued_at_deadlines(dr, session=session)
 
                 if was_finished:
                     dr.state = dag_run_state
diff --git a/airflow-core/src/airflow/serialization/definitions/dag.py 
b/airflow-core/src/airflow/serialization/definitions/dag.py
index c529bf95ade..64ceeff7ccc 100644
--- a/airflow-core/src/airflow/serialization/definitions/dag.py
+++ b/airflow-core/src/airflow/serialization/definitions/dag.py
@@ -795,7 +795,7 @@ class SerializedDAG:
                     deadline_time = 
deserialized_deadline_alert.reference.evaluate_with(
                         session=session,
                         interval=interval,
-                        # TODO : Pretty sure we can drop these last two; 
verify after testing is complete
+                        dagrun=orm_dagrun,
                         dag_id=self.dag_id,
                         run_id=run_id,
                     )
diff --git a/airflow-core/src/airflow/serialization/definitions/deadline.py 
b/airflow-core/src/airflow/serialization/definitions/deadline.py
index 25399aabc62..c7f1f1ee111 100644
--- a/airflow-core/src/airflow/serialization/definitions/deadline.py
+++ b/airflow-core/src/airflow/serialization/definitions/deadline.py
@@ -27,7 +27,7 @@ import attrs
 from sqlalchemy import select
 
 from airflow._shared.timezones import timezone
-from airflow.models.deadline import classproperty
+from airflow.models.deadline import _get_evaluation_kwargs, classproperty
 from airflow.models.variable import Variable
 from airflow.utils.log.logging_mixin import LoggingMixin
 from airflow.utils.session import provide_session
@@ -39,6 +39,8 @@ if TYPE_CHECKING:
     from sqlalchemy import ColumnElement
     from sqlalchemy.orm import Session
 
+    from airflow.models.deadline import DeadlineDagRunProtocol
+
 logger = logging.getLogger(__name__)
 
 
@@ -95,33 +97,18 @@ class SerializedReferenceModels:
     class SerializedBaseDeadlineReference(LoggingMixin, ABC):
         """Base class for all serialized Deadline implementations."""
 
-        required_kwargs: set[str] = set()
-
         @classproperty
         def reference_name(cls: Any) -> str:
             return cls.__name__
 
         def evaluate_with(self, *, session: Session, interval: timedelta, 
**kwargs: Any) -> datetime | None:
-            """Validate the provided kwargs and evaluate this deadline with 
the given conditions."""
-            filtered_kwargs = {k: v for k, v in kwargs.items() if k in 
self.required_kwargs}
-
-            if missing_kwargs := self.required_kwargs - filtered_kwargs.keys():
-                raise ValueError(
-                    f"{self.__class__.__name__} is missing required 
parameters: {', '.join(missing_kwargs)}"
-                )
-
-            if extra_kwargs := kwargs.keys() - filtered_kwargs.keys():
-                self.log.debug(
-                    "%s ignoring unexpected parameters: %s",
-                    self.reference_name,
-                    ", ".join(extra_kwargs),
-                )
-
-            base_time = self._evaluate_with(session=session, **filtered_kwargs)
+            """Evaluate this deadline with the supplied context."""
+            evaluation_kwargs = _get_evaluation_kwargs(self, 
self._evaluate_with, kwargs)
+            base_time = self._evaluate_with(session=session, 
**evaluation_kwargs)
             return base_time + interval if base_time is not None else None
 
         @abstractmethod
-        def _evaluate_with(self, *, session: Session, **kwargs: Any) -> 
datetime | None:
+        def _evaluate_with(self, *, session: Session, dagrun: 
DeadlineDagRunProtocol) -> datetime | None:
             """Must be implemented by subclasses to perform the actual 
evaluation."""
             raise NotImplementedError
 
@@ -168,23 +155,14 @@ class SerializedReferenceModels:
     class DagRunLogicalDateDeadline(SerializedBaseDeadlineReference):
         """A deadline that returns a DagRun's logical date."""
 
-        required_kwargs = {"dag_id", "run_id"}
-
-        def _evaluate_with(self, *, session: Session, **kwargs: Any) -> 
datetime | None:
-            from airflow.models import DagRun
-
-            return _fetch_from_db(DagRun.logical_date, session=session, 
**kwargs)
+        def _evaluate_with(self, *, session: Session, dagrun: 
DeadlineDagRunProtocol) -> datetime | None:
+            return dagrun.logical_date
 
     class DagRunQueuedAtDeadline(SerializedBaseDeadlineReference):
         """A deadline that returns when a DagRun was queued."""
 
-        required_kwargs = {"dag_id", "run_id"}
-
-        @provide_session
-        def _evaluate_with(self, *, session: Session, **kwargs: Any) -> 
datetime | None:
-            from airflow.models import DagRun
-
-            return _fetch_from_db(DagRun.queued_at, session=session, **kwargs)
+        def _evaluate_with(self, *, session: Session, dagrun: 
DeadlineDagRunProtocol) -> datetime | None:
+            return dagrun.queued_at
 
     @dataclass
     class AverageRuntimeDeadline(SerializedBaseDeadlineReference):
@@ -193,7 +171,6 @@ class SerializedReferenceModels:
         DEFAULT_LIMIT = 10
         max_runs: int
         min_runs: int | None = None
-        required_kwargs = {"dag_id"}
 
         def __post_init__(self):
             if self.min_runs is None:
@@ -202,13 +179,13 @@ class SerializedReferenceModels:
                 raise ValueError("min_runs must be at least 1")
 
         @provide_session
-        def _evaluate_with(self, *, session: Session, **kwargs: Any) -> 
datetime | None:
-            from sqlalchemy import func, select, text
+        def _evaluate_with(self, *, session: Session, dagrun: 
DeadlineDagRunProtocol) -> datetime | None:
+            from sqlalchemy import func, text
 
             from airflow.models import DagRun
             from airflow.utils.state import DagRunState
 
-            dag_id = kwargs["dag_id"]
+            dag_id = dagrun.dag_id
 
             dialect = get_dialect_name(session)
 
@@ -279,7 +256,7 @@ class SerializedReferenceModels:
         """
         Wrapper for custom deadline references.
 
-        This class dynamically delegates to the wrapped reference for 
required_kwargs and evaluation logic.
+        This class dynamically delegates to the wrapped reference's evaluation 
logic.
         """
 
         def __init__(self, inner_ref):
@@ -290,23 +267,9 @@ class SerializedReferenceModels:
             return self.inner_ref.reference_name
 
         def evaluate_with(self, *, session: Session, interval: timedelta, 
**kwargs: Any) -> datetime | None:
-            """Validate the provided kwargs and evaluate this deadline with 
the given conditions."""
-            required_kwargs: set[str] = getattr(self.inner_ref, 
"required_kwargs", set())
-            filtered_kwargs = {k: v for k, v in kwargs.items() if k in 
required_kwargs}
-
-            if missing_kwargs := required_kwargs - filtered_kwargs.keys():
-                raise ValueError(
-                    f"{self.inner_ref.__class__.__name__} is missing required 
parameters: {', '.join(missing_kwargs)}"
-                )
-
-            if extra_kwargs := kwargs.keys() - filtered_kwargs.keys():
-                self.log.debug(
-                    "%s ignoring unexpected parameters: %s",
-                    self.reference_name,
-                    ", ".join(extra_kwargs),
-                )
-
-            deadline = self.inner_ref._evaluate_with(session=session, 
**filtered_kwargs)
+            """Evaluate the wrapped custom reference with the supplied 
context."""
+            evaluation_kwargs = _get_evaluation_kwargs(self.inner_ref, 
self.inner_ref._evaluate_with, kwargs)
+            deadline = self.inner_ref._evaluate_with(session=session, 
**evaluation_kwargs)
             return deadline + interval if deadline is not None else None
 
         def _evaluate_with(self, *, session: Session, **kwargs: Any) -> 
datetime | None:
@@ -365,23 +328,6 @@ SerializedReferenceModels.TYPES.DAGRUN = (
 )
 
 
-def _fetch_from_db(column, *, session: Session, dag_id: str, run_id: str) -> 
datetime | None:
-    """
-    Fetch a datetime column from the DagRun table.
-
-    :meta private:
-    """
-    from airflow.models import DagRun
-
-    row = session.execute(
-        select(column).where(DagRun.dag_id == dag_id, DagRun.run_id == run_id)
-    ).one_or_none()
-    if row is None:
-        logger.warning("Could not find DagRun for dag_id=%s, run_id=%s", 
dag_id, run_id)
-        return None
-    return row[0]
-
-
 @attrs.define(frozen=True)
 class SerializedVariableInterval:
     """Core-side serialized representation of a variable-backed deadline 
interval."""
diff --git a/airflow-core/tests/unit/models/test_deadline.py 
b/airflow-core/tests/unit/models/test_deadline.py
index 87c383d3e9c..6c09ff069b1 100644
--- a/airflow-core/tests/unit/models/test_deadline.py
+++ b/airflow-core/tests/unit/models/test_deadline.py
@@ -19,17 +19,17 @@ from __future__ import annotations
 import re
 from dataclasses import dataclass
 from datetime import datetime, timedelta
+from types import SimpleNamespace
 from typing import TYPE_CHECKING
 from unittest import mock
 
 import pytest
 import time_machine
 from sqlalchemy import select
-from sqlalchemy.exc import SQLAlchemyError
 
 from airflow.api_fastapi.core_api.datamodels.dag_run import DAGRunResponse
 from airflow.models import DagRun
-from airflow.models.deadline import Deadline, _fetch_from_db
+from airflow.models.deadline import Deadline, ReferenceModels
 from airflow.providers.standard.operators.empty import EmptyOperator
 from airflow.sdk import timezone
 from airflow.sdk.definitions.callback import AsyncCallback, SyncCallback
@@ -42,10 +42,7 @@ from airflow.sdk.definitions.deadline import (
     FixedDatetimeDeadline,
     deadline_reference,
 )
-from airflow.serialization.definitions.deadline import (
-    SerializedReferenceModels,
-    _fetch_from_db as _fetch_serialized_deadline_from_db,
-)
+from airflow.serialization.definitions.deadline import 
SerializedReferenceModels
 from airflow.utils.state import DagRunState
 
 from tests_common.test_utils import db
@@ -58,15 +55,6 @@ DAG_ID = "dag_id_1"
 INVALID_DAG_ID = "invalid_dag_id"
 INVALID_RUN_ID = -1
 
-REFERENCE_TYPES = [
-    pytest.param(SerializedReferenceModels.DagRunLogicalDateDeadline(), 
id="logical_date"),
-    pytest.param(SerializedReferenceModels.DagRunQueuedAtDeadline(), 
id="queued_at"),
-    
pytest.param(SerializedReferenceModels.FixedDatetimeDeadline(DEFAULT_DATE), 
id="fixed_deadline"),
-    pytest.param(
-        SerializedReferenceModels.AverageRuntimeDeadline(max_runs=10, 
min_runs=10), id="average_runtime"
-    ),
-]
-
 
 async def callback_for_deadline():
     """Used in a number of tests to confirm that Deadlines and DeadlineAlerts 
function correctly."""
@@ -338,168 +326,41 @@ class TestDeadline:
 
 
 @pytest.mark.db_test
-class TestCalculatedDeadlineDatabaseCalls:
+class TestCalculatedDeadlineReferences:
     @staticmethod
     def teardown_method():
         _clean_db()
 
     @pytest.mark.parametrize(
-        ("column", "conditions", "expected_query"),
-        [
-            pytest.param(
-                DagRun.logical_date,
-                {"dag_id": DAG_ID},
-                "SELECT dag_run.logical_date \nFROM dag_run \nWHERE 
dag_run.dag_id = :dag_id_1",
-                id="single_condition_logical_date",
-            ),
-            pytest.param(
-                DagRun.queued_at,
-                {"dag_id": DAG_ID},
-                "SELECT dag_run.queued_at \nFROM dag_run \nWHERE 
dag_run.dag_id = :dag_id_1",
-                id="single_condition_queued_at",
-            ),
-            pytest.param(
-                DagRun.logical_date,
-                {"dag_id": DAG_ID, "state": "running"},
-                "SELECT dag_run.logical_date \nFROM dag_run \nWHERE 
dag_run.dag_id = :dag_id_1 AND dag_run.state = :state_1",
-                id="multiple_conditions",
-            ),
-        ],
-    )
-    @mock.patch("sqlalchemy.orm.Session")
-    def test_fetch_from_db_success(self, mock_session, column, conditions, 
expected_query):
-        """Test successful database queries."""
-        mock_session.scalar.return_value = DEFAULT_DATE
-
-        result = _fetch_from_db(column, session=mock_session, **conditions)
-
-        assert isinstance(result, datetime)
-        mock_session.scalar.assert_called_once()
-
-        # Check that the correct query was constructed
-        call_args = mock_session.scalar.call_args[0][0]
-        assert str(call_args) == expected_query
-
-        # Verify the actual parameter values
-        compiled = call_args.compile()
-        for key, value in conditions.items():
-            # Note that SQLAlchemy appends the _1 to ensure unique template 
field names
-            assert compiled.params[f"{key}_1"] == value
-
-    @pytest.mark.parametrize(
-        ("use_valid_conditions", "scalar_side_effect", "expected_error", 
"expected_message"),
-        [
-            pytest.param(
-                False,
-                mock.DEFAULT,  # This will allow the call to pass through
-                AttributeError,
-                None,
-                id="invalid_attribute",
-            ),
-            pytest.param(
-                True,
-                SQLAlchemyError("Database connection failed"),
-                SQLAlchemyError,
-                "Database connection failed",
-                id="database_error",
-            ),
-            pytest.param(
-                True, lambda x: None, ValueError, "No matching record found in 
the database", id="no_results"
-            ),
-        ],
-    )
-    @mock.patch("sqlalchemy.orm.Session")
-    def test_fetch_from_db_error_cases(
-        self, mock_session, use_valid_conditions, scalar_side_effect, 
expected_error, expected_message
-    ):
-        """Test database access error handling."""
-        model_reference = DagRun.logical_date
-        conditions = {"dag_id": "test_dag"} if use_valid_conditions else 
{"non_existent_column": "some_value"}
-
-        # Configure mock session
-        mock_session.scalar.side_effect = scalar_side_effect
-
-        with pytest.raises(expected_error, match=expected_message):
-            _fetch_from_db(model_reference, session=mock_session, **conditions)
-
-    @pytest.mark.parametrize(
-        ("reference", "expected_column"),
+        ("reference", "attribute"),
         [
             pytest.param(
-                SerializedReferenceModels.DagRunLogicalDateDeadline(), 
DagRun.logical_date, id="logical_date"
-            ),
-            pytest.param(
-                SerializedReferenceModels.DagRunQueuedAtDeadline(), 
DagRun.queued_at, id="queued_at"
+                SerializedReferenceModels.DagRunLogicalDateDeadline(), 
"logical_date", id="logical_date"
             ),
+            pytest.param(SerializedReferenceModels.DagRunQueuedAtDeadline(), 
"queued_at", id="queued_at"),
             pytest.param(
-                SerializedReferenceModels.FixedDatetimeDeadline(DEFAULT_DATE), 
None, id="fixed_deadline"
-            ),
-            pytest.param(
-                SerializedReferenceModels.AverageRuntimeDeadline(max_runs=10, 
min_runs=10),
-                None,
-                id="average_runtime",
+                ReferenceModels.DagRunLogicalDateDeadline(), "logical_date", 
id="legacy_logical_date"
             ),
+            pytest.param(ReferenceModels.DagRunQueuedAtDeadline(), 
"queued_at", id="legacy_queued_at"),
         ],
     )
-    def test_deadline_database_integration(self, reference, expected_column, 
session):
-        """
-        Test database integration for all deadline types.
-
-        Verifies:
-        1. Calculated deadlines call _fetch_from_db with correct column.
-        2. Fixed deadlines do not interact with database.
-        3. Intervals are added to reference times.
-        """
-        conditions = {"dag_id": DAG_ID, "run_id": "dagrun_1"}
+    def test_dagrun_references_use_supplied_dagrun(self, reference, attribute, 
session):
+        """DagRun references use the in-memory DagRun instead of querying it 
again."""
+        dagrun = SimpleNamespace(dag_id=DAG_ID, logical_date=DEFAULT_DATE, 
queued_at=DEFAULT_DATE)
         interval = timedelta(hours=1)
-        with 
mock.patch("airflow.serialization.definitions.deadline._fetch_from_db") as 
mock_fetch:
-            mock_fetch.return_value = DEFAULT_DATE
-
-            if expected_column is not None:
-                result = reference.evaluate_with(session=session, 
interval=interval, **conditions)
-                mock_fetch.assert_called_once_with(expected_column, 
session=session, **conditions)
-            elif isinstance(reference, 
SerializedReferenceModels.AverageRuntimeDeadline):
-                with mock.patch("airflow._shared.timezones.timezone.utcnow") 
as mock_utcnow:
-                    mock_utcnow.return_value = DEFAULT_DATE
-                    # No DAG runs exist, so it should use 24-hour default
-                    result = reference.evaluate_with(session=session, 
interval=interval, dag_id=DAG_ID)
-                    mock_fetch.assert_not_called()
-                    # Should return None when no DAG runs exist
-                    assert result is None
-            else:
-                result = reference.evaluate_with(session=session, 
interval=interval)
-                mock_fetch.assert_not_called()
-                assert result == DEFAULT_DATE + interval
-
-    def 
test_serialized_fetch_from_db_returns_null_column_without_missing_dagrun_warning(
-        self, session, dag_maker, caplog
-    ):
-        with dag_maker(DAG_ID):
-            EmptyOperator(task_id="test_task")
-
-        dag_maker.create_dagrun(
-            logical_date=None,
-            run_id="manual__null_logical_date",
-            state=DagRunState.QUEUED,
-        )
-        session.commit()
 
-        with caplog.at_level("WARNING", 
logger="airflow.serialization.definitions.deadline"):
-            result = _fetch_serialized_deadline_from_db(
-                DagRun.logical_date, session=session, dag_id=DAG_ID, 
run_id="manual__null_logical_date"
+        assert getattr(dagrun, attribute) == DEFAULT_DATE
+        assert (
+            reference.evaluate_with(
+                session=session,
+                interval=interval,
+                dagrun=dagrun,
+                dag_id=DAG_ID,
+                run_id="dagrun_1",
+                unexpected="ignored",
             )
-
-        assert result is None
-        assert not any("Could not find DagRun" in record.message for record in 
caplog.records)
-
-    def test_serialized_fetch_from_db_logs_missing_dagrun(self, session, 
caplog):
-        with caplog.at_level("WARNING", 
logger="airflow.serialization.definitions.deadline"):
-            result = _fetch_serialized_deadline_from_db(
-                DagRun.logical_date, session=session, dag_id=DAG_ID, 
run_id="missing_run"
-            )
-
-        assert result is None
-        assert any("Could not find DagRun" in record.message for record in 
caplog.records)
+            == DEFAULT_DATE + interval
+        )
 
     def test_average_runtime_with_sufficient_history(self, session, dag_maker):
         """Test AverageRuntimeDeadline when enough historical data exists."""
@@ -530,7 +391,9 @@ class TestCalculatedDeadlineDatabaseCalls:
 
         with mock.patch("airflow._shared.timezones.timezone.utcnow") as 
mock_utcnow:
             mock_utcnow.return_value = DEFAULT_DATE
-            result = reference.evaluate_with(session=session, 
interval=interval, dag_id=DAG_ID)
+            result = reference.evaluate_with(
+                session=session, interval=interval, 
dagrun=SimpleNamespace(dag_id=DAG_ID)
+            )
 
             # Calculate expected average: sum(durations) / len(durations)
             expected_avg_seconds = sum(durations) / len(durations)
@@ -567,7 +430,9 @@ class TestCalculatedDeadlineDatabaseCalls:
 
         with mock.patch("airflow._shared.timezones.timezone.utcnow") as 
mock_utcnow:
             mock_utcnow.return_value = DEFAULT_DATE
-            result = reference.evaluate_with(session=session, 
interval=interval, dag_id=DAG_ID)
+            result = reference.evaluate_with(
+                session=session, interval=interval, 
dagrun=SimpleNamespace(dag_id=DAG_ID)
+            )
 
             # Should return None since insufficient runs
             assert result is None
@@ -601,7 +466,9 @@ class TestCalculatedDeadlineDatabaseCalls:
 
         with mock.patch("airflow._shared.timezones.timezone.utcnow") as 
mock_utcnow:
             mock_utcnow.return_value = DEFAULT_DATE
-            result = reference.evaluate_with(session=session, 
interval=interval, dag_id=DAG_ID)
+            result = reference.evaluate_with(
+                session=session, interval=interval, 
dagrun=SimpleNamespace(dag_id=DAG_ID)
+            )
 
             # Should calculate average from 3 runs
             expected_avg_seconds = sum(durations) / len(durations)  # 4200 
seconds
@@ -614,7 +481,9 @@ class TestCalculatedDeadlineDatabaseCalls:
 
         with mock.patch("airflow._shared.timezones.timezone.utcnow") as 
mock_utcnow:
             mock_utcnow.return_value = DEFAULT_DATE
-            result = reference.evaluate_with(session=session, 
interval=interval, dag_id=DAG_ID)
+            result = reference.evaluate_with(
+                session=session, interval=interval, 
dagrun=SimpleNamespace(dag_id=DAG_ID)
+            )
             assert result is None
 
     def test_average_runtime_min_runs_validation(self):
@@ -663,7 +532,9 @@ class TestCalculatedDeadlineDatabaseCalls:
 
         with mock.patch("airflow._shared.timezones.timezone.utcnow") as 
mock_utcnow:
             mock_utcnow.return_value = DEFAULT_DATE
-            result = reference.evaluate_with(session=session, 
interval=interval, dag_id=DAG_ID)
+            result = reference.evaluate_with(
+                session=session, interval=interval, 
dagrun=SimpleNamespace(dag_id=DAG_ID)
+            )
 
         # Average must be over the 3 successful 60s runs only (not the 36000s 
failures).
         expected = DEFAULT_DATE + timedelta(seconds=success_duration) + 
interval
@@ -687,61 +558,15 @@ class TestCalculatedDeadlineDatabaseCalls:
         session.commit()
 
         reference = 
SerializedReferenceModels.AverageRuntimeDeadline(max_runs=10, min_runs=3)
-        result = reference.evaluate_with(session=session, 
interval=timedelta(hours=1), dag_id=DAG_ID)
+        result = reference.evaluate_with(
+            session=session, interval=timedelta(hours=1), 
dagrun=SimpleNamespace(dag_id=DAG_ID)
+        )
         assert result is None
 
 
 class TestDeadlineReference:
     """DeadlineReference lives in definitions/deadlines.py but properly 
testing them requires DB access."""
 
-    DEFAULT_INTERVAL = timedelta(hours=1)
-    DEFAULT_ARGS = {"interval": DEFAULT_INTERVAL}
-
-    @pytest.mark.parametrize("reference", REFERENCE_TYPES)
-    @pytest.mark.db_test
-    def test_deadline_evaluate_with(self, reference, session):
-        """Test that all deadline types evaluate correctly with their required 
conditions."""
-        conditions = {
-            "dag_id": DAG_ID,
-            "run_id": "dagrun_1",
-            "unexpected": "param",  # Add an unexpected parameter.
-            "extra": "kwarg",  # Add another unexpected parameter.
-        }
-
-        with mock.patch.object(reference, "_evaluate_with") as mock_evaluate:
-            mock_evaluate.return_value = DEFAULT_DATE
-
-            if reference.required_kwargs:
-                result = reference.evaluate_with(**self.DEFAULT_ARGS, 
session=session, **conditions)
-            else:
-                result = reference.evaluate_with(**self.DEFAULT_ARGS, 
session=session)
-
-            # Verify only expected kwargs are passed through.
-            expected_kwargs = {k: conditions[k] for k in 
reference.required_kwargs if k in conditions}
-            expected_kwargs["session"] = session
-
-            mock_evaluate.assert_called_once_with(**expected_kwargs)
-
-            assert result == DEFAULT_DATE + self.DEFAULT_INTERVAL
-
-    @pytest.mark.parametrize("reference", REFERENCE_TYPES)
-    @pytest.mark.db_test
-    def test_deadline_missing_required_kwargs(self, reference, session):
-        """Test that deadlines raise appropriate errors for missing required 
parameters."""
-        if reference.required_kwargs:
-            with pytest.raises(
-                ValueError, match=re.escape(f"{reference.__class__.__name__} 
is missing required parameters:")
-            ) as raised_exception:
-                reference.evaluate_with(session=session, **self.DEFAULT_ARGS)
-
-            assert all(substring in str(raised_exception.value) for substring 
in reference.required_kwargs)
-        else:
-            # Let the lack of an exception here effectively assert that no 
exception is raised.
-            reference.evaluate_with(session=session, **self.DEFAULT_ARGS)
-
-        for required_param in reference.required_kwargs:
-            assert required_param in str(raised_exception.value)
-
     def test_deadline_reference_creation(self):
         """Test that DeadlineReference provides consistent interface and 
types."""
         fixed_reference = DeadlineReference.FIXED_DATETIME(DEFAULT_DATE)
diff --git a/airflow-core/tests/unit/models/test_deadline_alert.py 
b/airflow-core/tests/unit/models/test_deadline_alert.py
index 56ed2f8cc86..54a138b64a0 100644
--- a/airflow-core/tests/unit/models/test_deadline_alert.py
+++ b/airflow-core/tests/unit/models/test_deadline_alert.py
@@ -17,6 +17,7 @@
 from __future__ import annotations
 
 from datetime import timedelta
+from types import SimpleNamespace
 from unittest.mock import Mock
 
 import pytest
@@ -24,6 +25,7 @@ import time_machine
 from sqlalchemy import select
 
 from airflow._shared.timezones import timezone
+from airflow.exceptions import RemovedInAirflow4Warning
 from airflow.models.deadline_alert import DeadlineAlert
 from airflow.models.serialized_dag import SerializedDagModel
 from airflow.sdk.definitions.deadline import BaseDeadlineReference, 
DeadlineReference
@@ -218,23 +220,83 @@ class TestDeadlineAlert:
 
         wrapper = 
SerializedReferenceModels.SerializedCustomReference(inner_ref)
 
-        wrapper.evaluate_with(
+        with pytest.warns(RemovedInAirflow4Warning, match="required_kwargs is 
deprecated"):
+            wrapper.evaluate_with(
+                session=None,
+                interval=timedelta(hours=1),
+                dag_id="test_dag",
+                run_id="test_run",
+                extra_param="should_be_filtered",
+            )
+
+        inner_ref._evaluate_with.assert_called_once_with(session=None, 
dag_id="test_dag", run_id="test_run")
+
+        # try calling with missing required parameters
+        with pytest.warns(RemovedInAirflow4Warning, match="required_kwargs is 
deprecated"):
+            with pytest.raises(ValueError, match="missing required parameters: 
run_id"):
+                wrapper.evaluate_with(
+                    session=None,
+                    interval=timedelta(hours=1),
+                    dag_id="test_dag",
+                )
+
+    def test_serialized_custom_reference_receives_dagrun(self):
+        class DagRunReference(BaseDeadlineReference):
+            def _evaluate_with(self, *, session, dagrun):
+                return dagrun.queued_at
+
+        wrapper = 
SerializedReferenceModels.SerializedCustomReference(DagRunReference())
+        dagrun = SimpleNamespace(queued_at=DEFAULT_DATE)
+
+        assert wrapper.evaluate_with(
             session=None,
             interval=timedelta(hours=1),
+            dagrun=dagrun,
             dag_id="test_dag",
             run_id="test_run",
-            extra_param="should_be_filtered",
-        )
+            unexpected="ignored",
+        ) == DEFAULT_DATE + timedelta(hours=1)
 
-        inner_ref._evaluate_with.assert_called_once_with(session=None, 
dag_id="test_dag", run_id="test_run")
+    def 
test_serialized_custom_reference_receives_dagrun_with_var_keyword_arguments(self):
+        class DagRunReference(BaseDeadlineReference):
+            def _evaluate_with(self, *, session, dagrun, **kwargs):
+                return dagrun.queued_at
 
-        # try calling with missing required parameters
-        with pytest.raises(ValueError, match="missing required parameters: 
run_id"):
-            wrapper.evaluate_with(
-                session=None,
-                interval=timedelta(hours=1),
-                dag_id="test_dag",
-            )
+        wrapper = 
SerializedReferenceModels.SerializedCustomReference(DagRunReference())
+        dagrun = SimpleNamespace(queued_at=DEFAULT_DATE)
+
+        assert wrapper.evaluate_with(
+            session=None,
+            interval=timedelta(hours=1),
+            dagrun=dagrun,
+            dag_id="test_dag",
+            run_id="test_run",
+        ) == DEFAULT_DATE + timedelta(hours=1)
+
+    def 
test_serialized_custom_reference_var_keyword_receives_full_context(self):
+        class VarKeywordReference(BaseDeadlineReference):
+            received_kwargs: dict[str, object]
+
+            def _evaluate_with(self, *, session, **kwargs):
+                self.received_kwargs = kwargs
+                return DEFAULT_DATE
+
+        reference = VarKeywordReference()
+        wrapper = 
SerializedReferenceModels.SerializedCustomReference(reference)
+        dagrun = SimpleNamespace()
+
+        assert wrapper.evaluate_with(
+            session=None,
+            interval=timedelta(hours=1),
+            dagrun=dagrun,
+            dag_id="test_dag",
+            run_id="test_run",
+        ) == DEFAULT_DATE + timedelta(hours=1)
+        assert reference.received_kwargs == {
+            "dagrun": dagrun,
+            "dag_id": "test_dag",
+            "run_id": "test_run",
+        }
 
     def test_core_deadline_reference_treated_as_builtins(self):
         """Test that refs from airflow.models.deadline are still treated as 
builtins."""
diff --git a/task-sdk/src/airflow/sdk/definitions/deadline.py 
b/task-sdk/src/airflow/sdk/definitions/deadline.py
index 3ef17245803..61dbe09b57b 100644
--- a/task-sdk/src/airflow/sdk/definitions/deadline.py
+++ b/task-sdk/src/airflow/sdk/definitions/deadline.py
@@ -47,7 +47,8 @@ class BaseDeadlineReference(ABC):
     The actual evaluation logic (``_evaluate_with``) is in Core's 
``SerializedReferenceModels``.
 
     For custom deadline references, users should inherit from this class and 
implement
-    ``_evaluate_with()`` with deferred Core imports (imports inside the method 
body).  A custom
+    ``_evaluate_with()`` with deferred Core imports (imports inside the method 
body). Its
+    keyword-only ``dagrun`` parameter receives the DagRun being evaluated. A 
custom
     reference must be decorated with ``@deadline_reference`` and listed in the 
``deadline_references``
     attribute of an ``AirflowPlugin``; see 
:external:doc:`howto/deadline-alerts`.
     """
@@ -212,8 +213,8 @@ class DeadlineReference:
     The public interface class for all DeadlineReference options.
 
     This class provides a unified interface for working with Deadlines, 
supporting both
-    calculated deadlines (which fetch values from the database) and fixed 
deadlines
-    (which return a predefined datetime).
+    calculated deadlines, including references to the DagRun being evaluated 
and
+    historical runtime data, and fixed deadlines (which return a predefined 
datetime).
 
     ------
     Usage:
@@ -240,17 +241,15 @@ class DeadlineReference:
            ),
        )
 
-    3. Evaluating deadlines will ignore unexpected parameters:
+    3. Custom references receive the DagRun being evaluated:
 
     .. code-block:: python
 
-       # For deadlines requiring parameters:
-       deadline = DeadlineReference.DAGRUN_LOGICAL_DATE
-       deadline.evaluate_with(dag_id=dag.dag_id)
-
-       # For deadlines with no required parameters:
-       deadline = DeadlineReference.FIXED_DATETIME(datetime(2025, 5, 4))
-       deadline.evaluate_with()
+       class MyDeadlineReference(BaseDeadlineReference):
+           def _evaluate_with(self, *, session, dagrun):
+               # Add your business logic here; dagrun.logical_date is 
available to use.
+               my_datetime = my_business_logic(dagrun.logical_date)
+               return my_datetime
     """
 
     class TYPES:
@@ -395,11 +394,10 @@ def deadline_reference(deadline_reference_type=None):
         @deadline_reference()
         class MyCustomReference(BaseDeadlineReference):
             # By default, evaluate_with will be called when a new dagrun is 
created.
-            def _evaluate_with(self, *, session: Session, **kwargs) -> 
datetime:
-                # Put your business logic here (use deferred imports for Core 
types)
-                from airflow.models import DagRun
-
-                return some_datetime
+            def _evaluate_with(self, *, session: Session, dagrun) -> datetime:
+                # Add your business logic here; dagrun.logical_date is 
available to use.
+                my_datetime = my_business_logic(dagrun.logical_date)
+                return my_datetime
 
             def serialize_reference(self) -> dict:
                 return {"reference_type": self.reference_name}
@@ -408,9 +406,10 @@ def deadline_reference(deadline_reference_type=None):
         # Optionally, specify when it is calculated by providing a 
DeadlineReference.TYPES value.
         @deadline_reference(DeadlineReference.TYPES.DAGRUN_QUEUED)
         class MyQueuedRef(BaseDeadlineReference):
-            def _evaluate_with(self, *, session: Session, **kwargs) -> 
datetime:
-                # Put your business logic here
-                return some_datetime
+            def _evaluate_with(self, *, session: Session, dagrun) -> datetime:
+                # Add your business logic here; dagrun.queued_at is available 
to use.
+                my_datetime = my_business_logic(dagrun.queued_at)
+                return my_datetime
 
             def serialize_reference(self) -> dict:
                 return {"reference_type": self.reference_name}

Reply via email to