From 3b5621278fc9eb11086681359bf009b25205cc22 Mon Sep 17 00:00:00 2001 From: marcsello Date: Fri, 10 Dec 2021 23:04:41 +0100 Subject: [PATCH] Implemented stuff --- birb_scheduler/app.py | 4 +- birb_scheduler/config.py | 15 +++++- birb_scheduler/utils/__init__.py | 3 +- birb_scheduler/utils/redis_client.py | 3 ++ birb_scheduler/views/assignment_view.py | 68 ++++++++++++++++++++++++- requirements.txt | 2 +- 6 files changed, 88 insertions(+), 7 deletions(-) create mode 100644 birb_scheduler/utils/redis_client.py diff --git a/birb_scheduler/app.py b/birb_scheduler/app.py index 1be28f0..39d5dab 100644 --- a/birb_scheduler/app.py +++ b/birb_scheduler/app.py @@ -5,7 +5,7 @@ from flask import Flask from werkzeug.middleware.proxy_fix import ProxyFix # import stuff -from utils import register_all_error_handlers, register_health_checks +from utils import register_all_error_handlers, register_health_checks, redis_client # import views from views import AssignmentView @@ -34,7 +34,7 @@ app.config.from_object(Config) app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1) # init stuff - +redis_client.init_app(app) # register error handlers diff --git a/birb_scheduler/config.py b/birb_scheduler/config.py index 13d1873..2b60c69 100644 --- a/birb_scheduler/config.py +++ b/birb_scheduler/config.py @@ -1,6 +1,17 @@ import os +def parse_default_while_not_defined(): + envvar = os.environ.get("DEFAULT_WHILE_NOT_DEFINED") + + if not envvar: + return None, None + + envvar = envvar.split(';', 1)[2:] + + return envvar + + class Config: SECRET_KEY = os.environ.get('SECRET_KEY', os.urandom(12)) @@ -8,6 +19,8 @@ class Config: RELEASE_ID = os.environ.get("RELEASE_ID", "test") RELEASEMODE = os.environ.get("RELEASEMODE", "dev") + REDIS_URL = os.environ.get("REDIS_URL", "redis://localhost:6379/0") + DEFAULT_WHILE_NOT_DEFINED = parse_default_while_not_defined() - INFLUXDB_TIMEOUT = 30 + DEVICE_TIMEOUT = int(os.environ.get("DEVICE_TIMEOUT", 120)) diff --git a/birb_scheduler/utils/__init__.py b/birb_scheduler/utils/__init__.py index 7f80bad..67ec797 100644 --- a/birb_scheduler/utils/__init__.py +++ b/birb_scheduler/utils/__init__.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 from .require_decorators import json_required from .error_handlers import register_all_error_handlers -from .healthchecks import register_health_checks \ No newline at end of file +from .healthchecks import register_health_checks +from .redis_client import redis_client diff --git a/birb_scheduler/utils/redis_client.py b/birb_scheduler/utils/redis_client.py new file mode 100644 index 0000000..90e8358 --- /dev/null +++ b/birb_scheduler/utils/redis_client.py @@ -0,0 +1,3 @@ +from flask_redis import FlaskRedis + +redis_client = FlaskRedis() diff --git a/birb_scheduler/views/assignment_view.py b/birb_scheduler/views/assignment_view.py index fd9f224..d934673 100644 --- a/birb_scheduler/views/assignment_view.py +++ b/birb_scheduler/views/assignment_view.py @@ -1,7 +1,71 @@ #!/usr/bin/env python3 -from flask import jsonify, request, abort, current_app, Response +from typing import Optional +from flask import jsonify, request, abort, current_app +from utils import json_required, redis_client from flask_classful import FlaskView +import json + class AssignmentView(FlaskView): - pass + + @staticmethod + def _resolve_response(site: Optional[str]) -> dict: + site_url_map = redis_client.get("SITEURLMAP") + + if site_url_map: + site_url_map = json.loads(site_url_map.decode('utf-8')) + + if not site_url_map: + return { + "site": current_app.config['DEFAULT_WHILE_NOT_DEFINED'][0], + "url": current_app.config['DEFAULT_WHILE_NOT_DEFINED'][1], + "hard_default": True + } + + if not site: + return { + "site": current_app.config['DEFAULT_WHILE_NOT_DEFINED'][0], + "url": current_app.config['DEFAULT_WHILE_NOT_DEFINED'][1], + "hard_default": True + } + + if site not in site_url_map.keys(): + # This should be an internal server error instead + return { + "site": current_app.config['DEFAULT_WHILE_NOT_DEFINED'][0], + "url": current_app.config['DEFAULT_WHILE_NOT_DEFINED'][1], + "hard_default": True + } + + return { + "site": site, + "url": site_url_map[site], + "hard_default": False + } + + @json_required + def post(self): + device_id = request.json['device_id'] + + schedule_store_key = f"SCHEDULED:{device_id}" + + target_site = redis_client.get(schedule_store_key) + + if target_site: + target_site = target_site.decode('utf-8') + + if not target_site: + default_target = redis_client.get('DEFAULT:SCHEDULED') + + if default_target: + target_site = default_target.decode('utf-8') + redis_client.set(schedule_store_key, default_target) + + # Update (or set) TTL + redis_client.expire( + schedule_store_key, + current_app.config['DEVICE_TIMEOUT'] + ) + + return jsonify(self._resolve_response(target_site)) diff --git a/requirements.txt b/requirements.txt index 7b0005d..28e3584 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ sentry_sdk flask_minio py-healthcheck -Flask-InfluxDB~=0.3.3 +flask-redis jaeger-client Flask-Opentracing