Restore the ability to load the DB backend lazily
We removed this a while ago, but unfortunately Nova, Ironic and probably other projects still rely on this feature to prevent import cycles and postpone initialization of DB backend to the moment when oslo.config has already parsed the config files (the errors were hidden when we tested the original commit by the fact that we had lazy loading of engines in oslo.db code). This is needed in order to make transitioning of existing projects to oslo.db as smooth as possible. Blueprint: oslo-db-lib Change-Id: I9fe09c132c716345f1cef240483b023e850d4989
This commit is contained in:
parent
dadea37f3e
commit
a1a6357370
|
@ -22,6 +22,7 @@ API methods.
|
|||
|
||||
import functools
|
||||
import logging
|
||||
import threading
|
||||
import time
|
||||
|
||||
from openstack.common.db import exception
|
||||
|
@ -86,7 +87,8 @@ class wrap_db_retry(object):
|
|||
|
||||
|
||||
class DBAPI(object):
|
||||
def __init__(self, backend_name, backend_mapping=None, **kwargs):
|
||||
def __init__(self, backend_name, backend_mapping=None, lazy=False,
|
||||
**kwargs):
|
||||
"""Initialize the choosen DB API backend.
|
||||
|
||||
:param backend_name: name of the backend to load
|
||||
|
@ -95,6 +97,9 @@ class DBAPI(object):
|
|||
:param backend_mapping: backend name -> module/class to load mapping
|
||||
:type backend_mapping: dict
|
||||
|
||||
:param lazy: load the DB backend lazily on the first DB API method call
|
||||
:type lazy: bool
|
||||
|
||||
Keyword arguments:
|
||||
|
||||
:keyword use_db_reconnect: retry DB transactions on disconnect or not
|
||||
|
@ -114,14 +119,13 @@ class DBAPI(object):
|
|||
|
||||
"""
|
||||
|
||||
if backend_mapping is None:
|
||||
backend_mapping = {}
|
||||
self._backend = None
|
||||
self._backend_name = backend_name
|
||||
self._backend_mapping = backend_mapping or {}
|
||||
self._lock = threading.Lock()
|
||||
|
||||
# Import the untranslated name if we don't have a
|
||||
# mapping.
|
||||
backend_path = backend_mapping.get(backend_name, backend_name)
|
||||
backend_mod = importutils.import_module(backend_path)
|
||||
self.__backend = backend_mod.get_backend()
|
||||
if not lazy:
|
||||
self._load_backend()
|
||||
|
||||
self.use_db_reconnect = kwargs.get('use_db_reconnect', False)
|
||||
self.retry_interval = kwargs.get('retry_interval', 1)
|
||||
|
@ -129,9 +133,20 @@ class DBAPI(object):
|
|||
self.max_retry_interval = kwargs.get('max_retry_interval', 10)
|
||||
self.max_retries = kwargs.get('max_retries', 20)
|
||||
|
||||
def __getattr__(self, key):
|
||||
attr = getattr(self.__backend, key)
|
||||
def _load_backend(self):
|
||||
with self._lock:
|
||||
if not self._backend:
|
||||
# Import the untranslated name if we don't have a mapping
|
||||
backend_path = self._backend_mapping.get(self._backend_name,
|
||||
self._backend_name)
|
||||
backend_mod = importutils.import_module(backend_path)
|
||||
self._backend = backend_mod.get_backend()
|
||||
|
||||
def __getattr__(self, key):
|
||||
if not self._backend:
|
||||
self._load_backend()
|
||||
|
||||
attr = getattr(self._backend, key)
|
||||
if not hasattr(attr, '__call__'):
|
||||
return attr
|
||||
# NOTE(vsergeyev): If `use_db_reconnect` option is set to True, retry
|
||||
|
|
|
@ -71,6 +71,13 @@ class DBAPITestCase(test_utils.BaseTestCase):
|
|||
def test_dbapi_unknown_invalid_backend(self):
|
||||
self.assertRaises(ImportError, api.DBAPI, 'tests.unit.db.not_existent')
|
||||
|
||||
def test_dbapi_lazy_loading(self):
|
||||
dbapi = api.DBAPI('tests.unit.db.test_api', lazy=True)
|
||||
|
||||
self.assertIsNone(dbapi._backend)
|
||||
dbapi.api_class_call1(1, 'abc')
|
||||
self.assertIsNotNone(dbapi._backend)
|
||||
|
||||
|
||||
class DBReconnectTestCase(DBAPITestCase):
|
||||
def setUp(self):
|
||||
|
|
Loading…
Reference in New Issue