def load_task_binding(reference: TaskReference, dag_bag) -> TaskBinding:
"""Read only the current, authorized task attempt's small JSON binding."""
from airflow.api_fastapi.core_api.services.public.task_coordinates import resolve_task_scope
from airflow.models.task_coordinates import TaskCoordinateResolver
from airflow.models.taskinstance import TaskInstance
from airflow.models.xcom import XComModel
from airflow.utils.session import create_session
from sqlalchemy import select
with create_session() as session:
resolver = TaskCoordinateResolver(dag_bag, session)
scope = resolve_task_scope(
dag_id=reference.dag_id,
run_id=reference.run_id,
task_id=reference.task_id,
map_index=reference.map_index,
region_id=reference.region_id,
region_index=reference.region_index,
resolver=resolver,
)
task = session.scalar(
select(TaskInstance).where(
TaskInstance.dag_id == reference.dag_id,
TaskInstance.run_id == reference.run_id,
TaskInstance.task_id == reference.task_id,
TaskInstance.region_id == scope.region_id,
TaskInstance.region_index == scope.region_index,
)
)
if task is None or not runs_provider_operator(task, resolver):
raise failure("task_not_found", "This task has no Spark application binding.")
if task.try_number != reference.try_number:
raise failure(
"stale_attempt", "Select the current task attempt before managing its Spark application.", 409
)
producer = select(TaskInstance.id).where(TaskInstance.id == task.id)
row = session.scalar(
XComModel.get_many(run_id=reference.run_id, key=CONSOLE_XCOM_KEY, producer_ids=producer)
)
if row is None:
raise failure(
"binding_not_found", "The Spark application has not been submitted by this task attempt."
)
try:
# Do not invoke custom XCom deserializers or fetch arbitrary remote XCom objects.
value = json.loads(row.value) if isinstance(row.value, str) else row.value
binding = TaskBinding.model_validate(value)
except (ValueError, TypeError, ValidationError) as error:
raise failure(
"invalid_binding", "The task's Spark application binding is unavailable."
) from error
if binding.try_number != reference.try_number:
raise failure("stale_binding", "The Spark binding belongs to an earlier task attempt.", 409)
# Ownership comes from the authorized database task, never editable XCom data.
binding.task_context = AirflowTaskContext(
dag_id=task.dag_id,
run_id=task.run_id,
task_id=task.task_id,
map_index=resolver.public_map_index(task),
try_number=task.try_number,
region_id=task.region_id,
region_index=task.region_index,
)
return binding