]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Testing reveals that we have *no* weak references to any cx_Oracle connections...
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 9 Feb 2016 03:57:02 +0000 (22:57 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 9 Feb 2016 16:49:35 +0000 (11:49 -0500)
yet cx_Oracle still has open sessions that cannot be killed until process dies.
Oracle wins!   Add a completely separate DB reaper script that runs
after py.test is done.

(cherry picked from commit 11a8440bc43aa9f7eb6f2cb7b7f43e0cf6680f41)

lib/sqlalchemy/testing/provision.py
reap_oracle_dbs.py [new file with mode: 0644]

index b998b7f786d728c4177f022de1845f3ec3cf3fad..b928d006d3d077dba5705a0e49a3f89bbf70befc 100644 (file)
@@ -4,6 +4,8 @@ from sqlalchemy import exc
 from sqlalchemy.util import compat
 from . import config, engines
 import time
+import logging
+log = logging.getLogger(__name__)
 
 FOLLOWER_IDENT = None
 
@@ -229,12 +231,39 @@ def _oracle_configure_follower(config, ident):
     config.test_schema_2 = "%s_ts2" % ident
 
 
+def _ora_drop_ignore(conn, dbname):
+    try:
+        conn.execute("drop user %s cascade" % dbname)
+        log.info("Reaped db: %s" % dbname)
+        return True
+    except exc.DatabaseError as err:
+        log.warn("couldn't drop db: %s" % err)
+        return False
+
 @_drop_db.for_db("oracle")
 def _oracle_drop_db(cfg, eng, ident):
     with eng.connect() as conn:
-        conn.execute("drop user %s cascade" % ident)
-        conn.execute("drop user %s_ts1 cascade" % ident)
-        conn.execute("drop user %s_ts2 cascade" % ident)
+        # cx_Oracle seems to occasionally leak open connections when a large
+        # suite it run, even if we confirm we have zero references to
+        # connection objects.
+        # while there is a "kill session" command in Oracle,
+        # it unfortunately does not release the connection sufficiently.
+        _ora_drop_ignore(conn, ident)
+        _ora_drop_ignore(conn, "%s_ts1" % ident)
+        _ora_drop_ignore(conn, "%s_ts2" % ident)
+
+def reap_oracle_dbs(eng):
+    log.info("Reaping Oracle dbs...")
+    with eng.connect() as conn:
+        to_reap = conn.execute(
+                 "select u.username from all_users u where username "
+                 "like 'TEST_%' and not exists (select username "
+                 "from v$session where username=u.username)")
+        dropped = 0
+        for total, (username, ) in enumerate(to_reap, 1):
+            if _ora_drop_ignore(conn, username):
+                dropped += 1
+        log.info("Dropped %d out of %d stale databases detected", dropped, total)
 
 
 @_follower_url_from_main.for_db("oracle")
diff --git a/reap_oracle_dbs.py b/reap_oracle_dbs.py
new file mode 100644 (file)
index 0000000..ff638a0
--- /dev/null
@@ -0,0 +1,24 @@
+"""Drop Oracle databases that are left over from a 
+multiprocessing test run.
+
+Currently the cx_Oracle driver seems to sometimes not release a
+TCP connection even if close() is called, which prevents the provisioning
+system from dropping a database in-process.
+
+"""
+from sqlalchemy.testing.plugin import plugin_base
+from sqlalchemy.testing import engines
+from sqlalchemy.testing import provision
+import logging
+
+logging.basicConfig()
+logging.getLogger(provision.__name__).setLevel(logging.INFO)
+
+plugin_base.read_config()
+oracle = plugin_base.file_config.get('db', 'oracle')
+from sqlalchemy.testing import provision
+
+engine = engines.testing_engine(oracle, {})
+provision.reap_oracle_dbs(engine)
+
+