Skip to content

Commit 91d8161

Browse files
committed
use WaitStrategy._poll and with_transient_exceptions
1 parent ed1c991 commit 91d8161

File tree

1 file changed

+17
-52
lines changed

1 file changed

+17
-52
lines changed

modules/generic/testcontainers/generic/sql_utils.py

Lines changed: 17 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -14,69 +14,34 @@
1414

1515

1616
class SqlConnectWaitStrategy(WaitStrategy):
17-
"""
18-
Wait strategy that tests database connectivity until it succeeds or times out.
19-
20-
This strategy performs database connection testing using SQLAlchemy directly,
21-
handling transient connection errors and providing appropriate retry logic
22-
for database connectivity testing.
23-
"""
17+
"""Wait strategy for database connectivity testing using SQLAlchemy."""
2418

2519
def __init__(self):
2620
super().__init__()
27-
self.transient_exceptions = (TimeoutError, ConnectionError, *ADDITIONAL_TRANSIENT_ERRORS)
21+
# Configure transient exceptions using the framework's built-in method
22+
self.with_transient_exceptions(TimeoutError, ConnectionError, *ADDITIONAL_TRANSIENT_ERRORS)
2823

2924
def wait_until_ready(self, container: WaitStrategyTarget) -> None:
30-
"""
31-
Test database connectivity with retry logic until it succeeds or times out.
32-
33-
Args:
34-
container: The SQL container that must have get_connection_url method
35-
36-
Raises:
37-
TimeoutError: If connection fails after timeout
38-
AttributeError: If container doesn't have get_connection_url method
39-
ImportError: If SQLAlchemy is not installed
40-
Exception: Any non-transient errors from connection attempts
41-
"""
42-
import time
43-
25+
"""Test database connectivity with retry logic until success or timeout."""
4426
if not hasattr(container, "get_connection_url"):
4527
raise AttributeError(f"Container {container} must have a get_connection_url method")
4628

4729
try:
4830
import sqlalchemy
4931
except ImportError as e:
50-
logger.error("SQLAlchemy is required for database connectivity testing")
5132
raise ImportError("SQLAlchemy is required for database containers") from e
5233

53-
start_time = time.time()
54-
55-
while True:
56-
if time.time() - start_time > self._startup_timeout:
57-
raise TimeoutError(
58-
f"Database connection failed after {self._startup_timeout}s timeout. "
59-
f"Hint: Check if the container is ready and the database is accessible."
60-
)
61-
34+
def _test_connection() -> bool:
35+
"""Test database connection, returning True if successful."""
36+
engine = sqlalchemy.create_engine(container.get_connection_url())
6237
try:
63-
connection_url = container.get_connection_url()
64-
engine = sqlalchemy.create_engine(connection_url)
65-
66-
try:
67-
with engine.connect():
68-
logger.info("Database connection test successful")
69-
return
70-
except Exception as e:
71-
logger.debug(f"Database connection attempt failed: {e}")
72-
raise
73-
finally:
74-
engine.dispose()
75-
76-
except self.transient_exceptions as e:
77-
logger.debug(f"Connection attempt failed: {e}, retrying in {self._poll_interval}s...")
78-
except Exception as e:
79-
logger.error(f"Connection failed with non-transient error: {e}")
80-
raise
81-
82-
time.sleep(self._poll_interval)
38+
with engine.connect():
39+
logger.info("Database connection successful")
40+
return True
41+
finally:
42+
engine.dispose()
43+
44+
# Use the framework's built-in _poll method with automatic retry and transient exception handling
45+
result = self._poll(_test_connection)
46+
if not result:
47+
raise TimeoutError(f"Database connection failed after {self._startup_timeout}s timeout")

0 commit comments

Comments
 (0)