This repository has been archived on 2024-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
devicehub-teal/ereuse_devicehub/dispatchers.py
2019-01-23 16:55:04 +01:00

47 lines
1.7 KiB
Python

from threading import Lock
import sqlalchemy as sa
import werkzeug.exceptions
from werkzeug import wsgi
import ereuse_devicehub.config
from ereuse_devicehub.devicehub import Devicehub
from ereuse_devicehub.resources.inventory import Inventory
class PathDispatcher:
NOT_FOUND = werkzeug.exceptions.NotFound()
INV = Inventory
def __init__(self, config_cls=ereuse_devicehub.config.DevicehubConfig) -> None:
self.lock = Lock()
self.instances = {}
self.CONFIG = config_cls
self.engine = sa.create_engine(self.CONFIG.SQLALCHEMY_DATABASE_URI)
with self.lock:
self.instantiate()
if not self.instances:
raise ValueError('There are no Devicehub instances! Please, execute `dh init-db`.')
self.one_app = next(iter(self.instances.values()))
def __call__(self, environ, start_response):
if wsgi.get_path_info(environ).startswith('/users'):
# Not nice solution but it works well for now
# Return any app, as all apps can handle login
return self.call(self.one_app, environ, start_response)
inventory = wsgi.pop_path_info(environ)
with self.lock:
if inventory not in self.instances:
self.instantiate()
app = self.instances.get(inventory, self.NOT_FOUND)
return self.call(app, environ, start_response)
@staticmethod
def call(app, environ, start_response):
return app(environ, start_response)
def instantiate(self):
sel = sa.select([self.INV.id]).where(self.INV.id.notin_(self.instances.keys()))
for row in self.engine.execute(sel):
self.instances[row.id] = Devicehub(inventory=row.id)