mirror of
https://github.com/langgenius/dify.git
synced 2026-09-08 02:43:49 +08:00
fix: Working outside of application context. (#38300)
This commit is contained in:
parent
2ee7db27be
commit
826b259d9f
@ -10,18 +10,21 @@ def is_credential_exists(credential_id: str, credential_type: "PluginCredentialT
|
|||||||
"""
|
"""
|
||||||
Check if the credential still exists in the database.
|
Check if the credential still exists in the database.
|
||||||
|
|
||||||
|
Uses the configured SQLAlchemy session factory instead of Flask-SQLAlchemy's
|
||||||
|
``db.engine`` because workflow graph node construction may run without an
|
||||||
|
active Flask application context.
|
||||||
|
|
||||||
:param credential_id: The credential ID to check
|
:param credential_id: The credential ID to check
|
||||||
:param credential_type: The type of credential (MODEL or TOOL)
|
:param credential_type: The type of credential (MODEL or TOOL)
|
||||||
:return: True if credential exists, False otherwise
|
:return: True if credential exists, False otherwise
|
||||||
"""
|
"""
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
from sqlalchemy.orm import Session
|
|
||||||
|
|
||||||
from extensions.ext_database import db
|
from core.db import session_factory
|
||||||
from models.provider import ProviderCredential, ProviderModelCredential
|
from models.provider import ProviderCredential, ProviderModelCredential
|
||||||
from models.tools import BuiltinToolProvider
|
from models.tools import BuiltinToolProvider
|
||||||
|
|
||||||
with Session(db.engine) as session:
|
with session_factory.create_session() as session:
|
||||||
if credential_type == PluginCredentialType.MODEL:
|
if credential_type == PluginCredentialType.MODEL:
|
||||||
# Check both pre-defined and custom model credentials using a single UNION query
|
# Check both pre-defined and custom model credentials using a single UNION query
|
||||||
stmt = (
|
stmt = (
|
||||||
|
|||||||
@ -114,10 +114,11 @@ def test_is_credential_exists_by_type(
|
|||||||
scalar_result: str | None,
|
scalar_result: str | None,
|
||||||
expected: bool,
|
expected: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
mocker.patch("extensions.ext_database.db", new=SimpleNamespace(engine=object()))
|
session = mocker.MagicMock()
|
||||||
session_cls = mocker.patch("sqlalchemy.orm.Session")
|
|
||||||
session = session_cls.return_value.__enter__.return_value
|
|
||||||
session.scalar.return_value = scalar_result
|
session.scalar.return_value = scalar_result
|
||||||
|
session_context = mocker.MagicMock()
|
||||||
|
session_context.__enter__.return_value = session
|
||||||
|
mocker.patch("core.db.session_factory.create_session", return_value=session_context)
|
||||||
|
|
||||||
result = is_credential_exists("cred-1", credential_type)
|
result = is_credential_exists("cred-1", credential_type)
|
||||||
|
|
||||||
@ -128,11 +129,33 @@ def test_is_credential_exists_by_type(
|
|||||||
def test_is_credential_exists_returns_false_for_unknown_type(
|
def test_is_credential_exists_returns_false_for_unknown_type(
|
||||||
mocker: MockerFixture,
|
mocker: MockerFixture,
|
||||||
) -> None:
|
) -> None:
|
||||||
mocker.patch("extensions.ext_database.db", new=SimpleNamespace(engine=object()))
|
session = mocker.MagicMock()
|
||||||
session_cls = mocker.patch("sqlalchemy.orm.Session")
|
session_context = mocker.MagicMock()
|
||||||
session = session_cls.return_value.__enter__.return_value
|
session_context.__enter__.return_value = session
|
||||||
|
mocker.patch("core.db.session_factory.create_session", return_value=session_context)
|
||||||
|
|
||||||
result = is_credential_exists("cred-1", cast(PluginCredentialType, "unknown"))
|
result = is_credential_exists("cred-1", cast(PluginCredentialType, "unknown"))
|
||||||
|
|
||||||
assert result is False
|
assert result is False
|
||||||
session.scalar.assert_not_called()
|
session.scalar.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_credential_exists_uses_configured_session_factory_without_flask_app_context(
|
||||||
|
mocker: MockerFixture,
|
||||||
|
) -> None:
|
||||||
|
class RaisingDB:
|
||||||
|
@property
|
||||||
|
def engine(self):
|
||||||
|
raise RuntimeError("Working outside of application context.")
|
||||||
|
|
||||||
|
session = mocker.MagicMock()
|
||||||
|
session.scalar.return_value = "model-credential"
|
||||||
|
session_context = mocker.MagicMock()
|
||||||
|
session_context.__enter__.return_value = session
|
||||||
|
create_session = mocker.patch("core.db.session_factory.create_session", return_value=session_context)
|
||||||
|
mocker.patch("extensions.ext_database.db", new=RaisingDB())
|
||||||
|
|
||||||
|
result = is_credential_exists("cred-1", PluginCredentialType.MODEL)
|
||||||
|
|
||||||
|
assert result is True
|
||||||
|
create_session.assert_called_once_with()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user