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

pierrejeambrun pushed a commit to branch 
revert-62214-fix/thread-safe-auth-manager-init
in repository https://gitbox.apache.org/repos/asf/airflow.git

commit cb13865745b376e81945c6a03eaf4b45d065ccc1
Author: Pierre Jeambrun <[email protected]>
AuthorDate: Tue Feb 24 12:15:06 2026 +0100

    Revert "Fix race condition in auth manager initialization (#62214)"
    
    This reverts commit 5c9171af1a56b5b60bb121537159ceb9c4de9f73.
---
 airflow-core/src/airflow/api_fastapi/app.py        | 10 ++-----
 airflow-core/tests/unit/api_fastapi/test_app.py    | 35 ----------------------
 airflow-core/tests/unit/utils/test_db.py           |  3 --
 .../fab/auth_manager/cli_commands/utils.py         |  3 --
 .../unit/fab/auth_manager/api_fastapi/conftest.py  |  2 --
 .../fab/tests/unit/fab/auth_manager/conftest.py    |  5 ----
 .../unit/fab/auth_manager/test_fab_auth_manager.py |  6 ----
 .../tests/unit/fab/auth_manager/test_security.py   |  3 --
 .../fab/auth_manager/views/test_permissions.py     |  3 --
 .../unit/fab/auth_manager/views/test_roles_list.py |  3 --
 .../tests/unit/fab/auth_manager/views/test_user.py |  3 --
 .../unit/fab/auth_manager/views/test_user_edit.py  |  3 --
 .../unit/fab/auth_manager/views/test_user_stats.py |  3 --
 providers/fab/tests/unit/fab/www/test_auth.py      |  3 --
 .../fab/www/views/test_views_custom_user_views.py  |  3 --
 .../common/auth_backend/test_google_openid.py      |  7 -----
 .../unit/keycloak/auth_manager/routes/conftest.py  |  3 +-
 17 files changed, 3 insertions(+), 95 deletions(-)

diff --git a/airflow-core/src/airflow/api_fastapi/app.py 
b/airflow-core/src/airflow/api_fastapi/app.py
index 7367bdc5d67..30d151c0db7 100644
--- a/airflow-core/src/airflow/api_fastapi/app.py
+++ b/airflow-core/src/airflow/api_fastapi/app.py
@@ -17,7 +17,6 @@
 from __future__ import annotations
 
 import logging
-import threading
 from contextlib import AsyncExitStack, asynccontextmanager
 from functools import cache
 from typing import TYPE_CHECKING
@@ -58,7 +57,6 @@ log = logging.getLogger(__name__)
 
 class _AuthManagerState:
     instance: BaseAuthManager | None = None
-    _lock = threading.Lock()
 
 
 @asynccontextmanager
@@ -139,12 +137,8 @@ def get_auth_manager_cls() -> type[BaseAuthManager]:
 
 def create_auth_manager() -> BaseAuthManager:
     """Create the auth manager."""
-    if _AuthManagerState.instance is not None:
-        return _AuthManagerState.instance
-    with _AuthManagerState._lock:
-        if _AuthManagerState.instance is None:
-            auth_manager_cls = get_auth_manager_cls()
-            _AuthManagerState.instance = auth_manager_cls()
+    auth_manager_cls = get_auth_manager_cls()
+    _AuthManagerState.instance = auth_manager_cls()
     return _AuthManagerState.instance
 
 
diff --git a/airflow-core/tests/unit/api_fastapi/test_app.py 
b/airflow-core/tests/unit/api_fastapi/test_app.py
index fa46a0d1f32..1eb692e1864 100644
--- a/airflow-core/tests/unit/api_fastapi/test_app.py
+++ b/airflow-core/tests/unit/api_fastapi/test_app.py
@@ -16,7 +16,6 @@
 # under the License.
 from __future__ import annotations
 
-import threading
 from unittest import mock
 
 import pytest
@@ -119,37 +118,3 @@ def test_plugin_with_invalid_url_prefix(caplog, 
fastapi_apps, expected_message,
 
     assert any(expected_message in rec.message for rec in caplog.records)
     assert not any(r.path == invalid_path for r in app.routes)
-
-
-def test_create_auth_manager_thread_safety():
-    """Concurrent calls to create_auth_manager must return the same singleton 
instance."""
-    call_count = 0
-    singleton = None
-
-    class FakeAuthManager:
-        def __init__(self):
-            nonlocal call_count, singleton
-            call_count += 1
-            singleton = self
-
-    app_module.purge_cached_app()
-
-    results = []
-    barrier = threading.Barrier(10)
-
-    def call_create_auth_manager():
-        barrier.wait()
-        results.append(app_module.create_auth_manager())
-
-    with mock.patch.object(app_module, "get_auth_manager_cls", 
return_value=FakeAuthManager):
-        threads = [threading.Thread(target=call_create_auth_manager) for _ in 
range(10)]
-        for t in threads:
-            t.start()
-        for t in threads:
-            t.join()
-
-    assert len(results) == 10
-    assert all(r is singleton for r in results)
-    assert call_count == 1
-
-    app_module.purge_cached_app()
diff --git a/airflow-core/tests/unit/utils/test_db.py 
b/airflow-core/tests/unit/utils/test_db.py
index 6a5a7b05061..2e2e49907a2 100644
--- a/airflow-core/tests/unit/utils/test_db.py
+++ b/airflow-core/tests/unit/utils/test_db.py
@@ -250,9 +250,6 @@ class TestDb:
 
         mock_upgrade = mocker.patch("alembic.command.upgrade")
 
-        from airflow.api_fastapi.app import purge_cached_app
-
-        purge_cached_app()
         with conf_vars(auth):
             upgradedb()
 
diff --git 
a/providers/fab/src/airflow/providers/fab/auth_manager/cli_commands/utils.py 
b/providers/fab/src/airflow/providers/fab/auth_manager/cli_commands/utils.py
index d3459709572..6d2ed506930 100644
--- a/providers/fab/src/airflow/providers/fab/auth_manager/cli_commands/utils.py
+++ b/providers/fab/src/airflow/providers/fab/auth_manager/cli_commands/utils.py
@@ -29,7 +29,6 @@ from flask_sqlalchemy import SQLAlchemy
 from sqlalchemy.engine import make_url
 
 import airflow
-from airflow.api_fastapi.app import purge_cached_app
 from airflow.configuration import conf
 from airflow.exceptions import AirflowConfigException
 from airflow.providers.fab.www.extensions.init_appbuilder import 
init_appbuilder
@@ -51,8 +50,6 @@ def _return_appbuilder(app: Flask, db) -> AirflowAppBuilder:
 
 @contextmanager
 def get_application_builder() -> Generator[AirflowAppBuilder, None, None]:
-    _return_appbuilder.cache_clear()
-    purge_cached_app()
     static_folder = os.path.join(os.path.dirname(airflow.__file__), "www", 
"static")
     flask_app = Flask(__name__, static_folder=static_folder)
     webserver_config = conf.get_mandatory_value("fab", "config_file")
diff --git a/providers/fab/tests/unit/fab/auth_manager/api_fastapi/conftest.py 
b/providers/fab/tests/unit/fab/auth_manager/api_fastapi/conftest.py
index 27aafc3e117..fb884b8ede7 100644
--- a/providers/fab/tests/unit/fab/auth_manager/api_fastapi/conftest.py
+++ b/providers/fab/tests/unit/fab/auth_manager/api_fastapi/conftest.py
@@ -22,14 +22,12 @@ from contextlib import contextmanager
 import pytest
 from fastapi.testclient import TestClient
 
-from airflow.api_fastapi.app import purge_cached_app
 from airflow.api_fastapi.core_api.security import get_user as get_user_dep
 from airflow.providers.fab.auth_manager.fab_auth_manager import FabAuthManager
 
 
 @pytest.fixture(scope="module")
 def fab_auth_manager():
-    purge_cached_app()
     return FabAuthManager()
 
 
diff --git a/providers/fab/tests/unit/fab/auth_manager/conftest.py 
b/providers/fab/tests/unit/fab/auth_manager/conftest.py
index 0def443a7f3..2cad4b4db03 100644
--- a/providers/fab/tests/unit/fab/auth_manager/conftest.py
+++ b/providers/fab/tests/unit/fab/auth_manager/conftest.py
@@ -22,9 +22,7 @@ from pathlib import Path
 
 import pytest
 
-from airflow.api_fastapi.app import purge_cached_app
 from airflow.providers.fab.www import app
-from airflow.providers.fab.www.app import purge_cached_app as 
purge_fab_cached_app
 
 from tests_common.test_utils.config import conf_vars
 from unit.fab.decorators import dont_initialize_flask_app_submodules
@@ -32,9 +30,6 @@ from unit.fab.decorators import 
dont_initialize_flask_app_submodules
 
 @pytest.fixture(scope="session")
 def minimal_app_for_auth_api():
-    purge_cached_app()
-    purge_fab_cached_app()
-
     @dont_initialize_flask_app_submodules(
         skip_all_except=[
             "init_appbuilder",
diff --git a/providers/fab/tests/unit/fab/auth_manager/test_fab_auth_manager.py 
b/providers/fab/tests/unit/fab/auth_manager/test_fab_auth_manager.py
index 0e3bee5ed82..982a9ed3c75 100644
--- a/providers/fab/tests/unit/fab/auth_manager/test_fab_auth_manager.py
+++ b/providers/fab/tests/unit/fab/auth_manager/test_fab_auth_manager.py
@@ -160,12 +160,6 @@ def auth_manager():
 
 @pytest.fixture
 def flask_app():
-    from airflow.api_fastapi.app import purge_cached_app
-
-    purge_cached_app()
-    from airflow.providers.fab.www.app import purge_cached_app as 
purge_fab_cached_app
-
-    purge_fab_cached_app()
     with conf_vars(
         {
             (
diff --git a/providers/fab/tests/unit/fab/auth_manager/test_security.py 
b/providers/fab/tests/unit/fab/auth_manager/test_security.py
index ce182dc6b4f..350101b832a 100644
--- a/providers/fab/tests/unit/fab/auth_manager/test_security.py
+++ b/providers/fab/tests/unit/fab/auth_manager/test_security.py
@@ -211,9 +211,6 @@ def clear_db_before_test():
 
 @pytest.fixture(scope="module")
 def app():
-    from airflow.api_fastapi.app import purge_cached_app
-
-    purge_cached_app()
     with conf_vars(
         {
             (
diff --git 
a/providers/fab/tests/unit/fab/auth_manager/views/test_permissions.py 
b/providers/fab/tests/unit/fab/auth_manager/views/test_permissions.py
index f53f621e28e..fc1af4dfb3a 100644
--- a/providers/fab/tests/unit/fab/auth_manager/views/test_permissions.py
+++ b/providers/fab/tests/unit/fab/auth_manager/views/test_permissions.py
@@ -30,9 +30,6 @@ from unit.fab.utils import client_with_login
 
 @pytest.fixture(scope="module")
 def fab_app():
-    from airflow.api_fastapi.app import purge_cached_app
-
-    purge_cached_app()
     with conf_vars(
         {
             (
diff --git a/providers/fab/tests/unit/fab/auth_manager/views/test_roles_list.py 
b/providers/fab/tests/unit/fab/auth_manager/views/test_roles_list.py
index 50c7b2f0d2e..66192f919ad 100644
--- a/providers/fab/tests/unit/fab/auth_manager/views/test_roles_list.py
+++ b/providers/fab/tests/unit/fab/auth_manager/views/test_roles_list.py
@@ -30,9 +30,6 @@ from unit.fab.utils import client_with_login
 
 @pytest.fixture(scope="module")
 def fab_app():
-    from airflow.api_fastapi.app import purge_cached_app
-
-    purge_cached_app()
     with conf_vars(
         {
             (
diff --git a/providers/fab/tests/unit/fab/auth_manager/views/test_user.py 
b/providers/fab/tests/unit/fab/auth_manager/views/test_user.py
index 383e90e1b28..1ae942824c7 100644
--- a/providers/fab/tests/unit/fab/auth_manager/views/test_user.py
+++ b/providers/fab/tests/unit/fab/auth_manager/views/test_user.py
@@ -30,9 +30,6 @@ from unit.fab.utils import client_with_login
 
 @pytest.fixture(scope="module")
 def fab_app():
-    from airflow.api_fastapi.app import purge_cached_app
-
-    purge_cached_app()
     with conf_vars(
         {
             (
diff --git a/providers/fab/tests/unit/fab/auth_manager/views/test_user_edit.py 
b/providers/fab/tests/unit/fab/auth_manager/views/test_user_edit.py
index 0138af2703c..926753a04c2 100644
--- a/providers/fab/tests/unit/fab/auth_manager/views/test_user_edit.py
+++ b/providers/fab/tests/unit/fab/auth_manager/views/test_user_edit.py
@@ -30,9 +30,6 @@ from unit.fab.utils import client_with_login
 
 @pytest.fixture(scope="module")
 def fab_app():
-    from airflow.api_fastapi.app import purge_cached_app
-
-    purge_cached_app()
     with conf_vars(
         {
             (
diff --git a/providers/fab/tests/unit/fab/auth_manager/views/test_user_stats.py 
b/providers/fab/tests/unit/fab/auth_manager/views/test_user_stats.py
index 0758f122ebd..9a68e9bc8fe 100644
--- a/providers/fab/tests/unit/fab/auth_manager/views/test_user_stats.py
+++ b/providers/fab/tests/unit/fab/auth_manager/views/test_user_stats.py
@@ -30,9 +30,6 @@ from unit.fab.utils import client_with_login
 
 @pytest.fixture(scope="module")
 def fab_app():
-    from airflow.api_fastapi.app import purge_cached_app
-
-    purge_cached_app()
     with conf_vars(
         {
             (
diff --git a/providers/fab/tests/unit/fab/www/test_auth.py 
b/providers/fab/tests/unit/fab/www/test_auth.py
index a2b1bf9f3a0..7400ff2bf14 100644
--- a/providers/fab/tests/unit/fab/www/test_auth.py
+++ b/providers/fab/tests/unit/fab/www/test_auth.py
@@ -33,9 +33,6 @@ mock_call = Mock()
 
 @pytest.fixture
 def app():
-    from airflow.api_fastapi.app import purge_cached_app
-
-    purge_cached_app()
     with conf_vars(
         {
             (
diff --git 
a/providers/fab/tests/unit/fab/www/views/test_views_custom_user_views.py 
b/providers/fab/tests/unit/fab/www/views/test_views_custom_user_views.py
index 9663f14fff4..2cfcb3f35fb 100644
--- a/providers/fab/tests/unit/fab/www/views/test_views_custom_user_views.py
+++ b/providers/fab/tests/unit/fab/www/views/test_views_custom_user_views.py
@@ -69,9 +69,6 @@ def delete_roles(app):
 
 @pytest.fixture
 def app():
-    from airflow.api_fastapi.app import purge_cached_app
-
-    purge_cached_app()
     with conf_vars(
         {
             (
diff --git 
a/providers/google/tests/unit/google/common/auth_backend/test_google_openid.py 
b/providers/google/tests/unit/google/common/auth_backend/test_google_openid.py
index 7183e248993..fc91814441b 100644
--- 
a/providers/google/tests/unit/google/common/auth_backend/test_google_openid.py
+++ 
b/providers/google/tests/unit/google/common/auth_backend/test_google_openid.py
@@ -34,8 +34,6 @@ if not AIRFLOW_V_3_0_PLUS:
         allow_module_level=True,
     )
 
-from airflow.api_fastapi.app import purge_cached_app
-
 from tests_common.test_utils.config import conf_vars
 
 
@@ -44,11 +42,6 @@ def google_openid_app():
     if importlib.util.find_spec("flask_session") is None:
         return None
 
-    purge_cached_app()
-    from airflow.providers.fab.www.app import purge_cached_app as 
purge_fab_cached_app
-
-    purge_fab_cached_app()
-
     def factory():
         with conf_vars(
             {
diff --git 
a/providers/keycloak/tests/unit/keycloak/auth_manager/routes/conftest.py 
b/providers/keycloak/tests/unit/keycloak/auth_manager/routes/conftest.py
index 8706c569e0d..e5ea6131155 100644
--- a/providers/keycloak/tests/unit/keycloak/auth_manager/routes/conftest.py
+++ b/providers/keycloak/tests/unit/keycloak/auth_manager/routes/conftest.py
@@ -23,7 +23,7 @@ import pytest
 import time_machine
 from fastapi.testclient import TestClient
 
-from airflow.api_fastapi.app import create_app, purge_cached_app
+from airflow.api_fastapi.app import create_app
 from airflow.providers.keycloak.auth_manager.constants import (
     CONF_CLIENT_ID_KEY,
     CONF_CLIENT_SECRET_KEY,
@@ -40,7 +40,6 @@ if TYPE_CHECKING:
 
 @pytest.fixture
 def client():
-    purge_cached_app()
     with conf_vars(
         {
             (

Reply via email to