fix: dbmodal test connection error timeout (#20068)
* fix: check for connect on ping * clean up merge * fix merge * precommit
This commit is contained in:
parent
9cdaa28042
commit
5111011de9
|
|
@ -23,6 +23,7 @@ from flask import current_app as app
|
|||
from flask_appbuilder.security.sqla.models import User
|
||||
from flask_babel import gettext as _
|
||||
from func_timeout import func_timeout, FunctionTimedOut
|
||||
from sqlalchemy.engine import Engine
|
||||
from sqlalchemy.exc import DBAPIError, NoSuchModuleError
|
||||
|
||||
from superset.commands.base import BaseCommand
|
||||
|
|
@ -82,36 +83,41 @@ class TestConnectionDatabaseCommand(BaseCommand):
|
|||
action="test_connection_attempt",
|
||||
engine=database.db_engine_spec.__name__,
|
||||
)
|
||||
with closing(engine.raw_connection()) as conn:
|
||||
try:
|
||||
alive = func_timeout(
|
||||
int(
|
||||
app.config[
|
||||
"TEST_DATABASE_CONNECTION_TIMEOUT"
|
||||
].total_seconds()
|
||||
),
|
||||
engine.dialect.do_ping,
|
||||
args=(conn,),
|
||||
)
|
||||
except (sqlite3.ProgrammingError, RuntimeError):
|
||||
# SQLite can't run on a separate thread, so ``func_timeout`` fails
|
||||
# RuntimeError catches the equivalent error from duckdb.
|
||||
alive = engine.dialect.do_ping(conn)
|
||||
except FunctionTimedOut as ex:
|
||||
raise SupersetTimeoutException(
|
||||
error_type=SupersetErrorType.CONNECTION_DATABASE_TIMEOUT,
|
||||
message=(
|
||||
"Please check your connection details and database "
|
||||
"settings, and ensure that your database is accepting "
|
||||
"connections, then try connecting again."
|
||||
),
|
||||
level=ErrorLevel.ERROR,
|
||||
extra={"sqlalchemy_uri": database.sqlalchemy_uri},
|
||||
) from ex
|
||||
except Exception: # pylint: disable=broad-except
|
||||
alive = False
|
||||
if not alive:
|
||||
raise DBAPIError(None, None, None)
|
||||
|
||||
def ping(engine: Engine) -> bool:
|
||||
with closing(engine.raw_connection()) as conn:
|
||||
return engine.dialect.do_ping(conn)
|
||||
|
||||
try:
|
||||
alive = func_timeout(
|
||||
int(
|
||||
app.config[
|
||||
"TEST_DATABASE_CONNECTION_TIMEOUT"
|
||||
].total_seconds()
|
||||
),
|
||||
ping,
|
||||
args=(engine,),
|
||||
)
|
||||
|
||||
except (sqlite3.ProgrammingError, RuntimeError):
|
||||
# SQLite can't run on a separate thread, so ``func_timeout`` fails
|
||||
# RuntimeError catches the equivalent error from duckdb.
|
||||
alive = engine.dialect.do_ping(engine)
|
||||
except FunctionTimedOut as ex:
|
||||
raise SupersetTimeoutException(
|
||||
error_type=SupersetErrorType.CONNECTION_DATABASE_TIMEOUT,
|
||||
message=(
|
||||
"Please check your connection details and database settings, "
|
||||
"and ensure that your database is accepting connections, "
|
||||
"then try connecting again."
|
||||
),
|
||||
level=ErrorLevel.ERROR,
|
||||
extra={"sqlalchemy_uri": database.sqlalchemy_uri},
|
||||
) from ex
|
||||
except Exception: # pylint: disable=broad-except
|
||||
alive = False
|
||||
if not alive:
|
||||
raise DBAPIError(None, None, None)
|
||||
|
||||
# Log succesful connection test with engine
|
||||
event_logger.log_with_context(
|
||||
|
|
@ -144,6 +150,7 @@ class TestConnectionDatabaseCommand(BaseCommand):
|
|||
)
|
||||
raise DatabaseSecurityUnsafeError(message=str(ex)) from ex
|
||||
except SupersetTimeoutException as ex:
|
||||
|
||||
event_logger.log_with_context(
|
||||
action=f"test_connection_error.{ex.__class__.__name__}",
|
||||
engine=database.db_engine_spec.__name__,
|
||||
|
|
|
|||
Loading…
Reference in New Issue