From fa789984f4c66b6e0c27a46550c4f6b40a492357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Mart=C3=ADnez=20Portela?= Date: Sat, 10 Jun 2023 15:55:43 +0200 Subject: [PATCH] Implement long-operation cache. --- scripts/gen_centered_graph.py | 3 +- scripts/ops_cache.py | 75 +++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/scripts/gen_centered_graph.py b/scripts/gen_centered_graph.py index 8176e16..fce246e 100644 --- a/scripts/gen_centered_graph.py +++ b/scripts/gen_centered_graph.py @@ -5,10 +5,9 @@ import ops_cache import copy import tempfile -# TODO: Cache results # TODO: Properly render outgouing links -# @ops_cache() +@ops_cache.cache def gen(headline_id, graph): reference_node = headline_id diff --git a/scripts/ops_cache.py b/scripts/ops_cache.py index e69de29..45c1431 100644 --- a/scripts/ops_cache.py +++ b/scripts/ops_cache.py @@ -0,0 +1,75 @@ +import sqlite3 +import json +import logging +from typing import Optional +import xdg +import os +import datetime + +CACHE_DB: Optional[sqlite3.Connection] = None +CACHE_PATH = os.path.join(xdg.xdg_cache_home(), 'codigoparallevar', 'ops.sqlite3') + +def init_db(): + global CACHE_DB + + os.makedirs(os.path.dirname(CACHE_PATH), exist_ok=True) + CACHE_DB = sqlite3.connect(CACHE_PATH) + + cur = CACHE_DB.cursor() + cur.execute('''CREATE TABLE IF NOT EXISTS ops( + in_val TEXT PRIMARY KEY, + code TEXT, + out_val TEXT, + added_at DateTime + ); + ''') + CACHE_DB.commit() + cur.close() + +def query_cache(in_val, code): + if CACHE_DB is None: + init_db() + assert CACHE_DB is not None + cur = CACHE_DB.cursor() + cur.execute('''SELECT out_val FROM ops WHERE in_val = ? AND code = ?''', (in_val, code)) + + # Should return only one result, right? 🤷 + results = cur.fetchall() + assert len(results) < 2 + if len(results) == 0: + return None + else: + return results[0][0] + +def save_cache(in_val, code, out_val): + if CACHE_DB is None: + init_db() + assert CACHE_DB is not None + cur = CACHE_DB.cursor() + cur.execute(''' + INSERT INTO ops(in_val, code, out_val, added_at) + VALUES (?, ?, ?, ?);''', + (in_val, code, out_val, datetime.datetime.now())) + CACHE_DB.commit() + cur.close() + +def cache(fun): + fun_code = fun.__code__.co_code.decode('latin-1') + def wrapped(*kargs, **kwargs): + in_val = json.dumps({ + 'kargs': kargs, + 'kwargs': kwargs, + 'fun_code': fun_code, + }) + + cache_result = query_cache(in_val, fun_code) + found_in_cache = cache_result is not None + if not found_in_cache: + out_val = fun(*kargs, **kwargs) + save_cache(in_val, fun_code, out_val) + else: + out_val = cache_result + + logging.info("{} bytes in, {} bytes out (in_cache: {})".format(len(in_val), len(out_val), found_in_cache)) + return out_val + return wrapped