Broken connections in pool become busy indefinitely · Issue #221 · oracle/python-oracledb (original) (raw)
- What versions are you using?
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.16.0.0.0
DEBUG: platform.platform: Linux-5.15.0-1042-azure-x86_64-with-glibc2.35
DEBUG: sys.maxsize > 2**32: True
DEBUG: platform.python_version: 3.10.9
DEBUG: oracledb.__version__: 1.4.0
- Is it an error or a hang or a crash?
Hang (acquiring a connection is not possible if all connections are busy) - What error(s) or behavior you are seeing?
Some network interruptions cause pool connection(s) to remain in busy list indefinitely.
Unfortunately I was unable to simulate the network interruption that reproduces the issue.
- Does your application call init_oracle_client()?
No
- Include a runnable Python script that shows the problem.
Following call is made every 10s:
await oracleStorage.ping()
class AsyncHelper: @staticmethod async def execute_io_bound(func: Callable[..., T], *args, **kwargs) -> T: """Execute an io-bound (sync) function in a separate thread pool so it does not block the asyncio thread."""
loop = asyncio.get_running_loop()
# default asyncio executor is a ThreadPoolExecutor, appropriate for io-bound tasks like DB queries.
return await loop.run_in_executor(None, functools.partial(func, *args, **kwargs))
class OracleStorage(): def init(self): self._pool = None
@property
def pool(self) -> oracledb.ConnectionPool:
if self._pool is None:
self._connect()
return self._pool
def _connect(self):
logging.debug(f"oracledb.__version__: {oracledb.version}")
# Create a connection pool
self._pool = oracledb.create_pool(
connection_id_prefix="firewall-api_",
dsn="...", # DSN with ewallet and failover options
user="...",
password="...",
min=1,
max=1,
getmode=oracledb.POOL_GETMODE_TIMEDWAIT,
wait_timeout=30000,
purity=oracledb.PURITY_NEW,
expire_time=1,
timeout=900,
)
logging.info("Connected to Oracle DB")
async def ping(self, timeout=900):
return await AsyncHelper.execute_io_bound(self._ping_sync, timeout=timeout)
def _ping_sync(self, timeout=900):
with self.pool.acquire() as connection:
prev_timeout = connection.call_timeout
connection.call_timeout = timeout
connection.ping()
connection.call_timeout = prev_timeout