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": {

Reply via email to