This is an automated email from the ASF dual-hosted git repository.
ashb 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 34520400a2c Remove unused span_status DB column and enum (#69278)
34520400a2c is described below
commit 34520400a2ca0fba70f5ab9ce7c876108f2e8af8
Author: Ei Sandi Aung <[email protected]>
AuthorDate: Wed Jul 8 13:58:19 2026 +0100
Remove unused span_status DB column and enum (#69278)
Around 3.2/3.3 we refactored how otel traces were emitted, meaning
these columns were unused, but we didn't remove them at the time.
---
airflow-core/docs/migrations-ref.rst | 4 +-
.../versions/0125_3_4_0_drop_span_status_column.py | 64 ++++++++++++++++++++++
airflow-core/src/airflow/models/dagrun.py | 4 --
airflow-core/src/airflow/models/taskinstance.py | 4 --
.../src/airflow/models/taskinstancehistory.py | 4 --
airflow-core/src/airflow/utils/db.py | 2 +-
airflow-core/src/airflow/utils/span_status.py | 33 -----------
airflow-core/tests/integration/otel/test_otel.py | 9 ++-
.../tests/unit/models/test_taskinstance.py | 2 -
contributing-docs/14_metadata_database_updates.rst | 4 +-
.../src/airflow_breeze/utils/selective_checks.py | 1 -
.../ci/prek/known_airflow_core_utils_modules.txt | 1 -
scripts/cov/core_coverage.py | 1 -
scripts/in_container/run_migration_round_trip.py | 1 -
14 files changed, 74 insertions(+), 60 deletions(-)
diff --git a/airflow-core/docs/migrations-ref.rst
b/airflow-core/docs/migrations-ref.rst
index 975d35981fe..6419525c8ab 100644
--- a/airflow-core/docs/migrations-ref.rst
+++ b/airflow-core/docs/migrations-ref.rst
@@ -39,7 +39,9 @@ Here's the list of all the Database Migrations that are
executed via when you ru
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
| Revision ID | Revises ID | Airflow Version | Description
|
+=========================+==================+===================+==============================================================+
-| ``5a5d3253e946`` (head) | ``d2f4e1b3c5a7`` | ``3.4.0`` | Add GIN
index on asset_event.extra for PostgreSQL. |
+| ``436dc127462c`` (head) | ``5a5d3253e946`` | ``3.4.0`` | Drop
span_status column. |
++-------------------------+------------------+-------------------+--------------------------------------------------------------+
+| ``5a5d3253e946`` | ``d2f4e1b3c5a7`` | ``3.4.0`` | Add GIN
index on asset_event.extra for PostgreSQL. |
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
| ``d2f4e1b3c5a7`` | ``9ff64e1c35d3`` | ``3.3.0`` | Add
partition_date to asset_partition_dag_run. |
+-------------------------+------------------+-------------------+--------------------------------------------------------------+
diff --git
a/airflow-core/src/airflow/migrations/versions/0125_3_4_0_drop_span_status_column.py
b/airflow-core/src/airflow/migrations/versions/0125_3_4_0_drop_span_status_column.py
new file mode 100644
index 00000000000..6e1123adf98
--- /dev/null
+++
b/airflow-core/src/airflow/migrations/versions/0125_3_4_0_drop_span_status_column.py
@@ -0,0 +1,64 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+Drop span_status column.
+
+Revision ID: 436dc127462c
+Revises: 5a5d3253e946
+Create Date: 2026-07-02 15:54:02.509006
+
+"""
+
+from __future__ import annotations
+
+import sqlalchemy as sa
+from alembic import op
+
+from airflow.migrations.utils import disable_sqlite_fkeys
+
+revision = "436dc127462c"
+down_revision = "5a5d3253e946"
+branch_labels = None
+depends_on = None
+airflow_version = "3.4.0"
+
+TABLES = ["dag_run", "task_instance", "task_instance_history"]
+
+
+def upgrade():
+ """Apply drop span_status column."""
+ with disable_sqlite_fkeys(op):
+ for table_name in TABLES:
+ with op.batch_alter_table(table_name) as batch_op:
+ batch_op.drop_column("span_status")
+
+
+def downgrade():
+ """Unapply drop span_status column."""
+ with disable_sqlite_fkeys(op):
+ for table_name in TABLES:
+ with op.batch_alter_table(table_name) as batch_op:
+ batch_op.add_column(
+ sa.Column(
+ "span_status",
+ sa.VARCHAR(length=250),
+ server_default=sa.text("'not_started'"),
+ nullable=False,
+ )
+ )
diff --git a/airflow-core/src/airflow/models/dagrun.py
b/airflow-core/src/airflow/models/dagrun.py
index 27751ed8b56..edc4d903aa2 100644
--- a/airflow-core/src/airflow/models/dagrun.py
+++ b/airflow-core/src/airflow/models/dagrun.py
@@ -90,7 +90,6 @@ from airflow.utils.helpers import chunks, is_container,
prune_dict
from airflow.utils.log.logging_mixin import LoggingMixin
from airflow.utils.retries import retry_db_transaction
from airflow.utils.session import NEW_SESSION, provide_session
-from airflow.utils.span_status import SpanStatus
from airflow.utils.sqlalchemy import (
ExtendedJSON,
UtcDateTime,
@@ -265,9 +264,6 @@ class DagRun(Base, LoggingMixin):
context_carrier: Mapped[dict[str, Any] | None] = mapped_column(
MutableDict.as_mutable(ExtendedJSON), nullable=True
)
- span_status: Mapped[str] = mapped_column(
- String(250), server_default=SpanStatus.NOT_STARTED, nullable=False
- )
created_dag_version_id: Mapped[UUID | None] = mapped_column(
Uuid(),
ForeignKey("dag_version.id", name="created_dag_version_id_fkey",
ondelete="set null"),
diff --git a/airflow-core/src/airflow/models/taskinstance.py
b/airflow-core/src/airflow/models/taskinstance.py
index c5b4f4ef542..8d1276999a2 100644
--- a/airflow-core/src/airflow/models/taskinstance.py
+++ b/airflow-core/src/airflow/models/taskinstance.py
@@ -106,7 +106,6 @@ from airflow.utils.net import get_hostname
from airflow.utils.platform import getuser
from airflow.utils.retries import run_with_db_retries
from airflow.utils.session import NEW_SESSION, create_session, provide_session
-from airflow.utils.span_status import SpanStatus
from airflow.utils.sqlalchemy import ExecutorConfigType, ExtendedJSON,
UtcDateTime
from airflow.utils.state import DagRunState, State, TaskInstanceState
@@ -599,9 +598,6 @@ class TaskInstance(Base, LoggingMixin, BaseWorkload):
)
_rendered_map_index: Mapped[str | None] =
mapped_column("rendered_map_index", String(250), nullable=True)
context_carrier: Mapped[dict | None] =
mapped_column(MutableDict.as_mutable(ExtendedJSON), nullable=True)
- span_status: Mapped[str] = mapped_column(
- String(250), server_default=SpanStatus.NOT_STARTED, nullable=False
- )
external_executor_id: Mapped[str | None] = mapped_column(Text(),
nullable=True)
diff --git a/airflow-core/src/airflow/models/taskinstancehistory.py
b/airflow-core/src/airflow/models/taskinstancehistory.py
index 47cfdb68ae5..1f741507bd5 100644
--- a/airflow-core/src/airflow/models/taskinstancehistory.py
+++ b/airflow-core/src/airflow/models/taskinstancehistory.py
@@ -45,7 +45,6 @@ from airflow.models.base import Base, StringID
from airflow.models.hitl import HITLDetail
from airflow.models.hitl_history import HITLDetailHistory
from airflow.utils.session import NEW_SESSION, provide_session
-from airflow.utils.span_status import SpanStatus
from airflow.utils.sqlalchemy import (
ExecutorConfigType,
ExtendedJSON,
@@ -103,9 +102,6 @@ class TaskInstanceHistory(Base):
)
rendered_map_index: Mapped[str | None] = mapped_column(String(250),
nullable=True)
context_carrier: Mapped[dict | None] =
mapped_column(MutableDict.as_mutable(ExtendedJSON), nullable=True)
- span_status: Mapped[str] = mapped_column(
- String(250), server_default=SpanStatus.NOT_STARTED, nullable=False
- )
external_executor_id: Mapped[str | None] = mapped_column(Text(),
nullable=True)
trigger_id: Mapped[int | None] = mapped_column(Integer, nullable=True)
diff --git a/airflow-core/src/airflow/utils/db.py
b/airflow-core/src/airflow/utils/db.py
index f02ef037174..ee10c008f9b 100644
--- a/airflow-core/src/airflow/utils/db.py
+++ b/airflow-core/src/airflow/utils/db.py
@@ -117,7 +117,7 @@ _REVISION_HEADS_MAP: dict[str, str] = {
"3.1.8": "509b94a1042d",
"3.2.0": "1d6611b6ab7c",
"3.3.0": "d2f4e1b3c5a7",
- "3.4.0": "5a5d3253e946",
+ "3.4.0": "436dc127462c",
}
# Prefix used to identify tables holding data moved during migration.
diff --git a/airflow-core/src/airflow/utils/span_status.py
b/airflow-core/src/airflow/utils/span_status.py
deleted file mode 100644
index 4d018e72aac..00000000000
--- a/airflow-core/src/airflow/utils/span_status.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-from __future__ import annotations
-
-from enum import Enum
-
-
-class SpanStatus(str, Enum):
- """All possible statuses for a span."""
-
- NOT_STARTED = "not_started"
- ACTIVE = "active"
- ENDED = "ended"
- SHOULD_END = "should_end"
- NEEDS_CONTINUANCE = "needs_continuance"
-
- def __str__(self) -> str:
- return self.value
diff --git a/airflow-core/tests/integration/otel/test_otel.py
b/airflow-core/tests/integration/otel/test_otel.py
index 6826d6cc877..ec6a7a6c94c 100644
--- a/airflow-core/tests/integration/otel/test_otel.py
+++ b/airflow-core/tests/integration/otel/test_otel.py
@@ -341,8 +341,8 @@ class TestOtelIntegration:
state = wait_for_dag_run(dag_id=dag_id, run_id=run_id,
max_wait_time=90)
assert state == State.SUCCESS, f"Dag run did not complete
successfully. Final state: {state}."
- # The ti span_status is updated while processing the executor
events,
- # which is after the dag_run state has been updated.
+ # wait_for_dag_run returns on the dag_run DB state, but OTel
metrics are exported
+ # asynchronously, so wait for them to reach stdout before we
capture it below.
time.sleep(10)
task_dict = dag.task_dict
@@ -508,11 +508,10 @@ class TestOtelIntegration:
run_id = unpause_trigger_dag_and_get_run_id(dag_id=dag_id,
conf=conf)
- # Skip the span_status check.
wait_for_dag_run(dag_id=dag_id, run_id=run_id, max_wait_time=90)
- # The ti span_status is updated while processing the executor
events,
- # which is after the dag_run state has been updated.
+ # wait_for_dag_run returns on the dag_run DB state, but spans
reach Jaeger
+ # asynchronously via the BatchSpanProcessor, so wait before
querying the trace below.
time.sleep(10)
print_ti_output_for_dag_run(dag_id=dag_id, run_id=run_id)
diff --git a/airflow-core/tests/unit/models/test_taskinstance.py
b/airflow-core/tests/unit/models/test_taskinstance.py
index bb9f09421bd..5f8e51c5b47 100644
--- a/airflow-core/tests/unit/models/test_taskinstance.py
+++ b/airflow-core/tests/unit/models/test_taskinstance.py
@@ -108,7 +108,6 @@ from airflow.ti_deps.deps.ready_to_reschedule import
ReadyToRescheduleDep
from airflow.ti_deps.deps.trigger_rule_dep import TriggerRuleDep,
_UpstreamTIStates
from airflow.timetables.simple import PartitionedAtRuntime
from airflow.utils.session import create_session, provide_session
-from airflow.utils.span_status import SpanStatus
from airflow.utils.state import DagRunState, State, TaskInstanceState
from airflow.utils.types import DagRunTriggeredByType, DagRunType
@@ -2588,7 +2587,6 @@ class TestTaskInstance:
"task_display_name": "Test Refresh from DB Task",
"dag_version_id": mock.ANY,
"context_carrier": {},
- "span_status": SpanStatus.ENDED,
"retry_delay_override": 60.0,
"retry_reason": "Rate limit, backing off",
}
diff --git a/contributing-docs/14_metadata_database_updates.rst
b/contributing-docs/14_metadata_database_updates.rst
index 6f3d6a3f22e..2bfefa89eaa 100644
--- a/contributing-docs/14_metadata_database_updates.rst
+++ b/contributing-docs/14_metadata_database_updates.rst
@@ -66,8 +66,8 @@ When rebasing your branch onto the latest ``main``, you may
encounter conflicts
The affected files may include:
-- ``docs/apache-airflow/migrations-ref.rst``
-- ``airflow/migrations/versions/1234_A_B_C_<your_migration_name>.py``
+- ``airflow-core/docs/migrations-ref.rst``
+-
``airflow-core/src/airflow/migrations/versions/1234_A_B_C_<your_migration_name>.py``
There should be another file, ``1234_A_B_C_<other_migration_name>.py``,
with the same ``1234_A_B_C`` prefix.
diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py
b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
index 89baca95145..6b7cfb5dd3a 100644
--- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py
+++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
@@ -483,7 +483,6 @@ CI_FILE_GROUP_MATCHES: HashableDict[FileGroupForCi] =
HashableDict(
FileGroupForCi.OTEL_FILES: [
r"^airflow-core/src/airflow/observability/.*",
r"^shared/observability/src/airflow_shared/observability/.*",
- r"^airflow-core/src/airflow/utils/span_status\.py$",
# The otel integration tests assert the exact span hierarchy that
# task_runner emits, so changes to either must exercise the
integration.
r"^airflow-core/tests/integration/otel/.*",
diff --git a/scripts/ci/prek/known_airflow_core_utils_modules.txt
b/scripts/ci/prek/known_airflow_core_utils_modules.txt
index bdd3a2aa51f..3b82f8a9e26 100644
--- a/scripts/ci/prek/known_airflow_core_utils_modules.txt
+++ b/scripts/ci/prek/known_airflow_core_utils_modules.txt
@@ -31,7 +31,6 @@ retries
scheduler_health
serve_logs
session
-span_status
sqlalchemy
state
strings
diff --git a/scripts/cov/core_coverage.py b/scripts/cov/core_coverage.py
index 2d812fef533..fdb6f6b457c 100644
--- a/scripts/cov/core_coverage.py
+++ b/scripts/cov/core_coverage.py
@@ -132,7 +132,6 @@ files_not_fully_covered = [
"airflow-core/src/airflow/utils/serve_logs.py",
"airflow-core/src/airflow/utils/session.py",
"airflow-core/src/airflow/utils/setup_teardown.py",
- "airflow-core/src/airflow/utils/span_status.py",
"airflow-core/src/airflow/utils/sqlalchemy.py",
"airflow-core/src/airflow/utils/state.py",
"airflow-core/src/airflow/utils/strings.py",
diff --git a/scripts/in_container/run_migration_round_trip.py
b/scripts/in_container/run_migration_round_trip.py
index f8b12d3dc94..e3ff6634e9c 100755
--- a/scripts/in_container/run_migration_round_trip.py
+++ b/scripts/in_container/run_migration_round_trip.py
@@ -126,7 +126,6 @@ SEED_VALUES: dict[str, dict[str, str]] = {
"state": "'success'",
"log_template_id": "1",
"run_after": "'2024-01-01 00:00:00+00:00'",
- "span_status": "'not_started'",
"clear_number": "0",
},
"task_instance": {