diff --git a/model.py b/model.py index 5304ccd..cea173b 100644 --- a/model.py +++ b/model.py @@ -1,9 +1,12 @@ import sqlite3 import typing +import json import sql_requests import utils +from EDMCLogging import get_main_logger +logger = get_main_logger() db: sqlite3.Connection = sqlite3.connect('squads_stat.sqlite3', check_same_thread=False) @@ -14,6 +17,15 @@ db.row_factory = lambda c, r: dict(zip([col[0] for col in c.description], r)) def get_activity_changes(platform: str, leaderboard_type: str, limit: int, low_timestamp, high_timestamp) -> list: + cache_key: str = f'{platform}_{leaderboard_type}_{limit}_{low_timestamp}_{high_timestamp}' + cached_result: typing.Union[str, None] = cache.get(cache_key) + + if cached_result is not None: + logger.debug(f'Cached result for {cache_key}') + return json.loads(cached_result) + + logger.debug(f'Not cached result for {cache_key}') + sql_req: sqlite3.Cursor = db.execute(sql_requests.select_activity_pretty_names, { 'LB_type': utils.LeaderboardTypes(leaderboard_type.lower()).value, 'platform': utils.Platform(platform.upper()).value, @@ -22,7 +34,10 @@ def get_activity_changes(platform: str, leaderboard_type: str, limit: int, low_t 'low_timestamp': low_timestamp }) - return sql_req.fetchall() + result: list = sql_req.fetchall() + cache.set(cache_key, json.dumps(result)) + + return result def insert_leaderboard_db(leaderboard_list: dict) -> None: @@ -57,6 +72,8 @@ def insert_leaderboard_db(leaderboard_list: dict) -> None: sql_requests.insert_leader_board, leaderboard) + cache.delete_all() # drop cache + def get_diff_action_id(action_id: int) -> list: """ @@ -66,6 +83,59 @@ def get_diff_action_id(action_id: int) -> list: :param action_id: :return: """ + cache_key: str = f'{action_id}' + cached_result: typing.Union[str, None] = cache.get(cache_key) + if cached_result is not None: + logger.debug(f'Cached result for {cache_key}') + return json.loads(cached_result) + + logger.debug(f'Not cached result for {cache_key}') sql_req: sqlite3.Cursor = db.execute(sql_requests.select_diff_by_action_id, {'action_id': action_id}) - return sql_req.fetchall() + result: list = sql_req.fetchall() + cache.set(cache_key, json.dumps(result)) + + return result + + +class Cache: + def __init__(self, db_conn: sqlite3.Connection, disabled: bool = False): + self.disabled = disabled + self.db: sqlite3.Connection = db_conn + with self.db: + self.db.execute("create table if not exists cache (key text unique, value text);") + + def set(self, key, value) -> None: + if self.disabled: + return + + with db: + if self.db.execute('select count(key) as count from cache where key = ?;', [key]).fetchone()['count'] == 1: + + # key exists, just need to update value + self.db.execute('update cache set value = ? where key = ?;', [value, key]) + else: + + # key doesn't exists, need to insert new row + self.db.execute('insert into cache (key, value) values (?, ?);', [key, value]) + + def get(self, key, default=None): + if self.disabled: + return + + res = self.db.execute('select value from cache where key = ?;', [key]).fetchone() + if res is None: + return default + + return res['value'] + + def delete(self, key): + self.db.execute('delete from cache where key = ?;', [key]) + + def delete_all(self): + logger.debug('Dropping cache') + with self.db: + self.db.execute('delete from cache;') + + +cache = Cache(db) diff --git a/web.py b/web.py index 9e565c4..ff4e51c 100644 --- a/web.py +++ b/web.py @@ -83,6 +83,16 @@ class MainPage: raise falcon.HTTPFound(f'/leaderboard/{var}') +class Cache: + def on_post(self, req: falcon.request.Request, resp: falcon.response.Response, action: str) -> None: + if action.lower() == 'drop': + model.cache.delete_all() + resp.status = falcon.HTTP_204 + return + + raise falcon.HTTPNotFound + + app = falcon.App() app.add_route('/api/activity/{leaderboard}', Activity()) app.add_route('/api/diff/{action_id}', ActivityDiff()) @@ -94,6 +104,8 @@ app.add_route('/js/{file}', JS()) app.add_route('/{var}', MainPage()) +app.add_route('/api/cache/{action}', Cache()) + application = app # for uwsgi if __name__ == '__main__':