Skip to content

Commit a99045a

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

File tree

1 file changed

+15
-52
lines changed

1 file changed

+15
-52
lines changed

modules/generic/testcontainers/generic/sql_utils.py

Lines changed: 15 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -14,69 +14,32 @@
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+
self.with_transient_exceptions(TimeoutError, ConnectionError, *ADDITIONAL_TRANSIENT_ERRORS)
2822

2923
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-
24+
"""Test database connectivity with retry logic until success or timeout."""
4425
if not hasattr(container, "get_connection_url"):
4526
raise AttributeError(f"Container {container} must have a get_connection_url method")
4627

4728
try:
4829
import sqlalchemy
4930
except ImportError as e:
50-
logger.error("SQLAlchemy is required for database connectivity testing")
5131
raise ImportError("SQLAlchemy is required for database containers") from e
5232

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-
33+
def _test_connection() -> bool:
34+
"""Test database connection, returning True if successful."""
35+
engine = sqlalchemy.create_engine(container.get_connection_url())
6236
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)
37+
with engine.connect():
38+
logger.info("Database connection successful")
39+
return True
40+
finally:
41+
engine.dispose()
42+
43+
result = self._poll(_test_connection)
44+
if not result:
45+
raise TimeoutError(f"Database connection failed after {self._startup_timeout}s timeout")

0 commit comments

Comments
 (0)