""" POC: Oracle async connectivity test — Săpt 1 Gate Correction 9 Tests native async oracledb.connect_async() vs sync baseline. Decision gate: if async latency acceptable → keep async-native (ad-hoc pattern). If degraded → use sync-facade with asyncio.run_in_executor. Usage: cd /workspace/roa2web backend/venv/bin/python poc/hello_oracle_async.py """ import asyncio import time import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'backend')) import oracledb HOST = "10.0.20.121" PORT = 1521 SERVICE_NAME = "ROA" USER = "CONTAFIN_ORACLE" SECRETS_FILE = os.path.join(os.path.dirname(__file__), '..', 'backend', 'secrets', 'central.oracle_pass') def read_password() -> str: with open(SECRETS_FILE) as f: return f.read().strip() async def test_async_connect(): print(f"[ASYNC] Connecting to {HOST}:{PORT}/{SERVICE_NAME} as {USER}") password = read_password() t0 = time.perf_counter() conn = await oracledb.connect_async( user=USER, password=password, host=HOST, port=PORT, service_name=SERVICE_NAME ) t_connect = time.perf_counter() - t0 print(f"[ASYNC] Connected in {t_connect*1000:.1f}ms") async with conn.cursor() as cur: # Basic connectivity t1 = time.perf_counter() await cur.execute("SELECT 1 FROM DUAL") row = await cur.fetchone() t_dual = time.perf_counter() - t1 print(f"[ASYNC] SELECT 1 FROM DUAL = {row[0]} ({t_dual*1000:.1f}ms)") # SYSDATE t2 = time.perf_counter() await cur.execute("SELECT SYSDATE FROM DUAL") row = await cur.fetchone() t_date = time.perf_counter() - t2 print(f"[ASYNC] SELECT SYSDATE = {row[0]} ({t_date*1000:.1f}ms)") # DEV_ORDL access t3 = time.perf_counter() await cur.execute("SELECT COUNT(*) FROM MARIUSM_AUTO.DEV_ORDL WHERE ROWNUM <= 1") row = await cur.fetchone() t_table = time.perf_counter() - t3 print(f"[ASYNC] SELECT COUNT(*) DEV_ORDL = {row[0]} ({t_table*1000:.1f}ms)") # Parallel queries test (proves concurrency benefit of async) print("[ASYNC] All queries via single cursor OK") await conn.close() total = time.perf_counter() - t0 print(f"[ASYNC] Total: {total*1000:.1f}ms ✅") async def test_async_pool(): """ Test sync pool in async context — matches existing oracle_pool.py pattern. Existing codebase uses oracledb.create_pool() (sync) + pool.acquire() (sync) + sync cursors inside async def. This is the established sync-facade pattern. Gate Correction 9: keep this pattern for service_auto (consistency). """ print("\n[POOL] Testing sync pool in async context (existing pattern)...") password = read_password() t0 = time.perf_counter() pool = oracledb.create_pool( user=USER, password=password, host=HOST, port=PORT, service_name=SERVICE_NAME, min=1, max=3, increment=1 ) t_pool = time.perf_counter() - t0 print(f"[POOL] Pool created in {t_pool*1000:.1f}ms (min=1, max=3)") # sync acquire in async def — matches oracle_pool.py:165 conn = pool.acquire() with conn.cursor() as cur: t1 = time.perf_counter() cur.execute("SELECT 1 FROM DUAL") row = cur.fetchone() t_q = time.perf_counter() - t1 print(f"[POOL] Sync query via pool: {row[0]} ({t_q*1000:.1f}ms)") conn.close() pool.close() print(f"[POOL] Pool closed ✅") async def main(): await test_async_connect() await test_async_pool() print("\n" + "="*50) print("GATE Correction 9 Summary:") print(" If latencies above are <50ms → async-native OK") print(" If >200ms or errors → use sync-facade pattern") print("="*50) if __name__ == "__main__": asyncio.run(main())