summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2015-09-22 12:34:52 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2015-09-22 13:45:58 -0400
commit7daffffafc8940a5097cdd33724eff1efaa33d1a (patch)
tree0accaf283d088f42073da42ed35bccc43c230d89
parentd87228c311a820a483b2db9171e70c93097085ee (diff)
downloadoslo-db-7daffffafc8940a5097cdd33724eff1efaa33d1a.tar.gz
Add support for pickling enginefacade context objects
In order to pickle a context object which refers to an active _TransactionContextTLocal, we have to use __reduce__ so that no database, engine, or session state is pickled, and only a constructor remains. Upon unpickling, the constructor will install a new, empty _TransactionContextTLocal on the new context, as is appropriate since this is a totally different context object than the original one. Change-Id: Ia50cf10ff91a013ee24773c095a3df69ae06847b
-rw-r--r--oslo_db/sqlalchemy/enginefacade.py3
-rw-r--r--oslo_db/tests/sqlalchemy/test_enginefacade.py18
2 files changed, 20 insertions, 1 deletions
diff --git a/oslo_db/sqlalchemy/enginefacade.py b/oslo_db/sqlalchemy/enginefacade.py
index cf7f149..8b241cf 100644
--- a/oslo_db/sqlalchemy/enginefacade.py
+++ b/oslo_db/sqlalchemy/enginefacade.py
@@ -569,6 +569,9 @@ class _TransactionContextTLocal(threading.local):
def __deepcopy__(self, memo):
return self
+ def __reduce__(self):
+ return _TransactionContextTLocal, ()
+
class _TransactionContextManager(object):
"""Provide context-management and decorator patterns for transactions.
diff --git a/oslo_db/tests/sqlalchemy/test_enginefacade.py b/oslo_db/tests/sqlalchemy/test_enginefacade.py
index 6893a93..4a2517e 100644
--- a/oslo_db/tests/sqlalchemy/test_enginefacade.py
+++ b/oslo_db/tests/sqlalchemy/test_enginefacade.py
@@ -13,6 +13,7 @@
import collections
import contextlib
import copy
+import pickle
import warnings
import mock
@@ -986,7 +987,7 @@ class LegacyIntegrationtest(test_base.DbTestCase):
class ThreadingTest(test_base.DbTestCase):
- """Test copying on new threads using real connections and sessions."""
+ """Test copy/pickle on new threads using real connections and sessions."""
def _assert_ctx_connection(self, context, connection):
self.assertIs(context.connection, connection)
@@ -1162,6 +1163,21 @@ class ThreadingTest(test_base.DbTestCase):
with self._patch_thread_ident():
go_one(context)
+ def test_contexts_picklable(self):
+ context = oslo_context.RequestContext()
+
+ with enginefacade.writer.using(context) as session:
+ self._assert_ctx_session(context, session)
+
+ pickled = pickle.dumps(context)
+
+ unpickled = pickle.loads(pickled)
+
+ with enginefacade.writer.using(unpickled) as session2:
+ self._assert_ctx_session(unpickled, session2)
+
+ assert session is not session2
+
class LiveFacadeTest(test_base.DbTestCase):
"""test using live SQL with test-provisioned databases.