Skip to content

Broken connections in pool become busy indefinitely #221

Closed
@7opf

Description

@7opf
  1. 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
  1. Is it an error or a hang or a crash?
    Hang (acquiring a connection is not possible if all connections are busy)

  2. 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.

  1. Does your application call init_oracle_client()?

No

  1. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions