diff --git a/brian_dashboard_manager/routes/update.py b/brian_dashboard_manager/routes/update.py index c5cd92368286154eaee415c5165b7376325707fb..7673e7a78222340f07c2bbdb747a808535283cd3 100644 --- a/brian_dashboard_manager/routes/update.py +++ b/brian_dashboard_manager/routes/update.py @@ -1,12 +1,14 @@ import datetime +import logging from flask import jsonify, Response -from concurrent.futures import ThreadPoolExecutor from flask import Blueprint, current_app from brian_dashboard_manager.routes import common from brian_dashboard_manager.grafana.provision import provision from brian_dashboard_manager import CONFIG_KEY +logger = logging.getLogger(__name__) + provision_state = { 'time': datetime.datetime.now(datetime.timezone.utc), 'provisioning': False @@ -29,13 +31,17 @@ def after_request(resp): return common.after_request(resp) -def provision_maybe(): +@routes.route('/', methods=['GET']) +def update(): """ - Check if we should provision in case of multiple requests hitting the endpoint. - We need to make sure we don't provision if another thread is still running. + This resource is used to trigger the dashboard provisioning to Grafana. + + The response will be formatted according to the following schema: + + .. asjson:: + brian_dashboard_manager.routes.update.UPDATE_RESPONSE_SCHEMA - :return: tuple of (bool, datetime) representing if we can provision - and the timestamp of the last provisioning, respectively. + :return: json """ global provision_state # noqa: F824 @@ -43,9 +49,10 @@ def provision_maybe(): now = datetime.datetime.now(datetime.timezone.utc) timestamp = provision_state['time'] provisioning = provision_state['provisioning'] + should = True - if provisioning and (now - timestamp).total_seconds() < 600: # lockout for 10 minutes at most - return False, timestamp + if provisioning and (now - timestamp).total_seconds() < 300: # lockout for 5 minutes at most + should = False def write_timestamp(timestamp, provisioning): provision_state['time'] = timestamp @@ -55,32 +62,18 @@ def provision_maybe(): now = datetime.datetime.now(datetime.timezone.utc) write_timestamp(now, False) - write_timestamp(now, True) - - executor = ThreadPoolExecutor(max_workers=1) - f = executor.submit(provision, current_app.config[CONFIG_KEY]) - f.add_done_callback(lambda _: _finish()) - return True, now - - -@routes.route('/', methods=['GET']) -def update(): - """ - This resource is used to trigger the provisioning to Grafana. - - It responds to the request immediately after starting - the provisioning process. - - The response will be formatted according to the following schema: + if should: + write_timestamp(now, True) - .. asjson:: - brian_dashboard_manager.routes.update.UPDATE_RESPONSE_SCHEMA + try: + provision(current_app.config[CONFIG_KEY]) + except Exception: + logger.exception("Error during provisioning:") + return jsonify({'data': {'message': 'Provisioning failed, check logs for details.'}}), 500 + finally: + _finish() - :return: json - """ - should, timestamp = provision_maybe() - if should: - return jsonify({'data': {'message': 'Provisioning dashboards!'}}) + return jsonify({'data': {'message': 'Provisioned dashboards!'}}) else: seconds_ago = (datetime.datetime.now(datetime.timezone.utc) - timestamp).total_seconds() message = f'Provision already in progress since {timestamp} ({seconds_ago:.2f} seconds ago).'