112 lines
3.2 KiB
Python
112 lines
3.2 KiB
Python
# combo - content management system
|
|
# Copyright (C) 2021 Entr'ouvert
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify it
|
|
# under the terms of the GNU Affero General Public License as published
|
|
# by the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import contextlib
|
|
import logging
|
|
import sys
|
|
from functools import wraps
|
|
|
|
from django.db import close_old_connections, connection
|
|
|
|
USE_UWSGI = 'uwsgi' in sys.modules
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def ensure_db(func):
|
|
"""Emulate Django"s setup/teardown of database connections before/after
|
|
each request"""
|
|
|
|
@wraps(func)
|
|
def f(*args, **kwargs):
|
|
close_old_connections()
|
|
try:
|
|
return func(*args, **kwargs)
|
|
finally:
|
|
close_old_connections()
|
|
|
|
return f
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def tenant_context(domain):
|
|
from hobo.multitenant.middleware import TenantMiddleware # pylint: disable=import-error
|
|
from tenant_schemas.utils import tenant_context # pylint: disable=import-error
|
|
|
|
tenant = TenantMiddleware.get_tenant_by_hostname(domain)
|
|
with tenant_context(tenant):
|
|
yield
|
|
|
|
|
|
def tenantspool(func):
|
|
"""Wrap a function with uwsgidecorators.spool storing and restoring the
|
|
current tenant."""
|
|
if not USE_UWSGI:
|
|
return func
|
|
|
|
from uwsgidecorators import spool
|
|
|
|
@ensure_db
|
|
@wraps(func)
|
|
def spooler_func(*args, **kwargs):
|
|
with contextlib.ExitStack() as stack:
|
|
if 'domain' in kwargs:
|
|
stack.enter_context(tenant_context(kwargs.pop('domain')))
|
|
try:
|
|
func(*args, **kwargs)
|
|
except Exception:
|
|
logger.exception('spooler: exception during %s(%s, %s)', func.__name__, args, kwargs)
|
|
else:
|
|
logger.info('spooler: success of %s(%s, %s)', func.__name__, args, kwargs)
|
|
|
|
# pass arguments as pickles
|
|
base_spooler = spool(pass_arguments=True)(spooler_func)
|
|
|
|
@wraps(func)
|
|
def spooler(*args, **kwargs):
|
|
domain = getattr(getattr(connection, 'tenant', None), 'domain_url', None)
|
|
if domain is not None:
|
|
kwargs['domain'] = domain
|
|
return base_spooler(*args, **kwargs)
|
|
|
|
return spooler
|
|
|
|
|
|
@tenantspool
|
|
def refresh_statistics_list():
|
|
from combo.apps.dataviz.utils import update_available_statistics
|
|
|
|
update_available_statistics()
|
|
|
|
|
|
@tenantspool
|
|
def refresh_statistics_data(cell_pk):
|
|
from combo.apps.dataviz.models import ChartNgCell, MissingRequest, MissingVariable
|
|
|
|
try:
|
|
cell = ChartNgCell.objects.get(pk=cell_pk)
|
|
except ChartNgCell.DoesNotExist:
|
|
return
|
|
|
|
try:
|
|
cell.get_statistic_data(invalidate_cache=True)
|
|
except (MissingRequest, MissingVariable):
|
|
return
|
|
|
|
if cell.statistic.service_slug != 'bijoe':
|
|
cell.update_subfilters()
|