-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix: Lazy behaviour. Connect to database on app.ready
- Loading branch information
Showing
5 changed files
with
72 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,70 @@ | ||
import functools | ||
|
||
from sqlalchemy import create_engine | ||
from sqlalchemy.orm import sessionmaker, close_all_sessions, Session | ||
from sqlalchemy.orm import sessionmaker, close_all_sessions, Session, \ | ||
scoped_session | ||
from yhttp.core import HTTPStatus | ||
|
||
|
||
class DatabaseManager: | ||
def __init__(self, app, basemodel): | ||
self.app = app | ||
class ORM: | ||
def __init__(self, basemodel, url=None): | ||
self.url = url | ||
self.engine = None | ||
self.sessionfactory = sessionmaker() | ||
self.basemodel = basemodel | ||
self.session = scoped_session(sessionmaker()) | ||
|
||
def __enter__(self) -> sessionmaker: | ||
if self.engine is None: | ||
if 'db' not in self.app.settings: | ||
raise ValueError( | ||
'Please provide db.url configuration entry, for example: ' | ||
'postgresql://:@/dbname' | ||
) | ||
|
||
self.engine = create_engine( | ||
self.app.settings.db.url, | ||
isolation_level='REPEATABLE READ' | ||
) | ||
def copy(self, url=None): | ||
return ORM(self.basemodel, url=url or self.app.settings.db.url) | ||
|
||
self.sessionfactory.configure(bind=self.engine) | ||
return self.sessionfactory | ||
def create_objects(self): | ||
return self.basemodel.metadata.create_all(self.engine) | ||
|
||
def __exit__(self, exc_type, exc_value, traceback): | ||
def connect(self, url=None): | ||
u = url or self.url | ||
assert self.engine is None | ||
assert u is not None | ||
|
||
self.engine = create_engine(u, isolation_level='REPEATABLE READ') | ||
self.session.configure(bind=self.engine) | ||
|
||
def disconnect(self): | ||
close_all_sessions() | ||
self.engine.dispose() | ||
self.engine = None | ||
|
||
def create_objects(self): | ||
return self.basemodel.metadata.create_all(self.engine) | ||
def __enter__(self) -> Session: | ||
self.connect() | ||
return self | ||
|
||
def __exit__(self, exc_type, exc_value, traceback): | ||
self.disconnect() | ||
|
||
def session(self) -> Session: | ||
return self.sessionfactory.begin() | ||
|
||
class ApplicationORM(ORM): | ||
def __init__(self, basemodel, app): | ||
self.app = app | ||
super().__init__(basemodel) | ||
|
||
def connect(self, url=None): | ||
if 'db' not in self.app.settings or 'url' not in self.app.settings.db: | ||
raise ValueError( | ||
'Please provide db.url configuration entry, for example: ' | ||
'postgresql://:@/dbname' | ||
) | ||
|
||
return super().connect(url=url or self.app.settings.db.url) | ||
|
||
def __call__(self, handler): | ||
@functools.wraps(handler) | ||
def outter(req, *a, **kw): | ||
with self.session() as session: | ||
req.dbsession = session | ||
try: | ||
return handler(req, *a, **kw) | ||
except HTTPStatus as ex: | ||
if ex.keepheaders: | ||
return ex | ||
|
||
raise | ||
finally: | ||
del req.dbsession | ||
def outter(*a, **kw): | ||
try: | ||
return handler(*a, **kw) | ||
except HTTPStatus as ex: | ||
if ex.keepheaders: | ||
return ex | ||
|
||
raise | ||
finally: | ||
self.session.reset() | ||
|
||
return outter |