Decoupled decorator from PreemptiveCache class
Coupling it led to problems (naturally) when there was no PreemptiveCache instance available yet.
This commit is contained in:
parent
6473937b75
commit
3de4f91f50
3 changed files with 40 additions and 32 deletions
|
|
@ -42,6 +42,7 @@ loginManager = None
|
|||
pluginManager = None
|
||||
appSessionManager = None
|
||||
pluginLifecycleManager = None
|
||||
preemptiveCache = None
|
||||
|
||||
principals = Principal(app)
|
||||
admin_permission = Permission(RoleNeed("admin"))
|
||||
|
|
@ -61,6 +62,7 @@ import octoprint.util
|
|||
import octoprint.filemanager.storage
|
||||
import octoprint.filemanager.analysis
|
||||
import octoprint.slicing
|
||||
from octoprint.server.util.flask import PreemptiveCache
|
||||
|
||||
from . import util
|
||||
|
||||
|
|
@ -142,6 +144,7 @@ class Server():
|
|||
global pluginManager
|
||||
global appSessionManager
|
||||
global pluginLifecycleManager
|
||||
global preemptiveCache
|
||||
global debug
|
||||
|
||||
from tornado.ioloop import IOLoop
|
||||
|
|
@ -185,6 +188,7 @@ class Server():
|
|||
printer = Printer(fileManager, analysisQueue, printerProfileManager)
|
||||
appSessionManager = util.flask.AppSessionManager()
|
||||
pluginLifecycleManager = LifecycleManager(pluginManager)
|
||||
preemptiveCache = PreemptiveCache(os.path.join(s.getBaseFolder("data"), "preemptive_cache_config.yaml"))
|
||||
|
||||
def octoprint_plugin_inject_factory(name, implementation):
|
||||
if not isinstance(implementation, octoprint.plugin.OctoPrintPlugin):
|
||||
|
|
@ -199,7 +203,8 @@ class Server():
|
|||
printer=printer,
|
||||
app_session_manager=appSessionManager,
|
||||
plugin_lifecycle_manager=pluginLifecycleManager,
|
||||
data_folder=os.path.join(settings().getBaseFolder("data"), name)
|
||||
data_folder=os.path.join(settings().getBaseFolder("data"), name),
|
||||
preemptive_cache=preemptiveCache
|
||||
)
|
||||
|
||||
def settings_plugin_inject_factory(name, implementation):
|
||||
|
|
@ -469,7 +474,7 @@ class Server():
|
|||
|
||||
# when we are through with that we also run our preemptive cache
|
||||
if settings().getBoolean(["devel", "cache", "preemptive"]):
|
||||
self._execute_preemptive_flask_caching()
|
||||
self._execute_preemptive_flask_caching(preemptiveCache)
|
||||
|
||||
import threading
|
||||
threading.Thread(target=work).start()
|
||||
|
|
@ -622,9 +627,6 @@ class Server():
|
|||
response.headers.add("X-Clacks-Overhead", "GNU Terry Pratchett")
|
||||
return response
|
||||
|
||||
preemptive_cache = octoprint.server.util.flask.PreemptiveCache(os.path.join(settings().getBaseFolder("data"), "preemptive_flask_cache.yaml"))
|
||||
preemptive_cache.attach_to_app(app)
|
||||
|
||||
def _setup_i18n(self, app):
|
||||
global babel
|
||||
global LOCALES
|
||||
|
|
@ -670,19 +672,16 @@ class Server():
|
|||
|
||||
self._register_template_plugins()
|
||||
|
||||
def _execute_preemptive_flask_caching(self):
|
||||
def _execute_preemptive_flask_caching(self, preemptive_cache):
|
||||
from werkzeug.test import EnvironBuilder
|
||||
import time
|
||||
|
||||
if not hasattr(app, "preemptive_cache"):
|
||||
return
|
||||
|
||||
# we clean up entries from our preemptive cache settings that haven't been
|
||||
# accessed longer than server.preemptiveCache.until days
|
||||
preemptive_cache_timeout = settings().getInt(["server", "preemptiveCache", "until"])
|
||||
cutoff_timestamp = time.time() + preemptive_cache_timeout * 24 * 60 * 60
|
||||
|
||||
cache_data = app.preemptive_cache.clean_all_data(lambda root, entries: filter(lambda entry: "_timestamp" in entry and entry["_timestamp"] <= cutoff_timestamp, entries))
|
||||
cache_data = preemptive_cache.clean_all_data(lambda root, entries: filter(lambda entry: "_timestamp" in entry and entry["_timestamp"] <= cutoff_timestamp, entries))
|
||||
if not cache_data:
|
||||
return
|
||||
|
||||
|
|
@ -697,7 +696,7 @@ class Server():
|
|||
|
||||
self._logger.info("Preemptively caching {} for {!r}".format(route, kwargs))
|
||||
builder = EnvironBuilder(**kwargs)
|
||||
with app.preemptive_cache.disable_timestamp_update():
|
||||
with preemptive_cache.disable_timestamp_update():
|
||||
app(builder.get_environ(), lambda *a, **kw: None)
|
||||
except:
|
||||
self._logger.exception("Error while trying to preemptively cache {} for {!r}".format(route, kwargs))
|
||||
|
|
|
|||
|
|
@ -387,21 +387,17 @@ class PreemptiveCache(object):
|
|||
self._logger = logging.getLogger(__name__ + "." + self.__class__.__name__)
|
||||
self._update_timestamp = True
|
||||
|
||||
def recorded(self, data, unless=None):
|
||||
def decorator(f):
|
||||
@functools.wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if not (callable(unless) and unless()):
|
||||
entry_data = data
|
||||
if callable(entry_data):
|
||||
entry_data = entry_data()
|
||||
def record(self, data, unless=None):
|
||||
if callable(unless) and unless():
|
||||
return
|
||||
|
||||
if entry_data is not None:
|
||||
from flask import request
|
||||
self.add_data(request.path, entry_data)
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
return decorator
|
||||
entry_data = data
|
||||
if callable(entry_data):
|
||||
entry_data = entry_data()
|
||||
|
||||
if entry_data is not None:
|
||||
from flask import request
|
||||
self.add_data(request.path, entry_data)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def disable_timestamp_update(self):
|
||||
|
|
@ -436,6 +432,10 @@ class PreemptiveCache(object):
|
|||
try:
|
||||
with open(self.cachefile, "r") as f:
|
||||
cache_data = yaml.safe_load(f)
|
||||
except IOError as e:
|
||||
import errno
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
except:
|
||||
self._logger.exception("Error while reading {}".format(self.cachefile))
|
||||
|
||||
|
|
@ -515,8 +515,15 @@ class PreemptiveCache(object):
|
|||
|
||||
self.set_data(root, [to_persist] + other)
|
||||
|
||||
def attach_to_app(self, app):
|
||||
app.preemptive_cache = self
|
||||
|
||||
def preemptively_cached(cache, data, unless=None):
|
||||
def decorator(f):
|
||||
@functools.wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
cache.record(data, unless=unless)
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
return decorator
|
||||
|
||||
|
||||
def add_non_caching_response_headers(response):
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ from flask import request, g, url_for, make_response, render_template, send_from
|
|||
import octoprint.plugin
|
||||
|
||||
from octoprint.server import app, userManager, pluginManager, gettext, \
|
||||
debug, LOCALES, VERSION, DISPLAY_VERSION, UI_API_KEY, BRANCH
|
||||
debug, LOCALES, VERSION, DISPLAY_VERSION, UI_API_KEY, BRANCH, preemptiveCache
|
||||
from octoprint.settings import settings
|
||||
|
||||
import re
|
||||
|
|
@ -27,8 +27,9 @@ _valid_id_re = re.compile("[a-z_]+")
|
|||
_valid_div_re = re.compile("[a-zA-Z_-]+")
|
||||
|
||||
@app.route("/")
|
||||
@app.preemptive_cache.recorded(data=lambda: dict(path=request.path, base_url=request.url_root, query_string="l10n={}".format(g.locale.language)) if g.locale else None,
|
||||
unless=lambda: request.url_root in settings().get(["server", "preemptiveCache", "exceptions"]))
|
||||
@util.flask.preemptively_cached(cache=preemptiveCache,
|
||||
data=lambda: dict(path=request.path, base_url=request.url_root, query_string="l10n={}".format(g.locale.language)) if g.locale else None,
|
||||
unless=lambda: request.url_root in settings().get(["server", "preemptiveCache", "exceptions"]))
|
||||
@util.flask.cached(timeout=-1,
|
||||
refreshif=lambda: util.flask.cache_check_headers() or "_refresh" in request.values,
|
||||
key=lambda: "view:{}:{}".format(request.base_url, g.locale.language if g.locale else "default"),
|
||||
|
|
@ -403,8 +404,9 @@ def robotsTxt():
|
|||
|
||||
|
||||
@app.route("/i18n/<string:locale>/<string:domain>.js")
|
||||
@app.preemptive_cache.recorded(data=lambda: dict(path=request.path, base_url=request.url_root),
|
||||
unless=lambda: request.url_root in settings().get(["server", "preemptiveCache", "exceptions"]))
|
||||
@util.flask.preemptively_cached(cache=preemptiveCache,
|
||||
data=lambda: dict(path=request.path, base_url=request.url_root),
|
||||
unless=lambda: request.url_root in settings().get(["server", "preemptiveCache", "exceptions"]))
|
||||
@util.flask.cached(timeout=-1,
|
||||
refreshif=lambda: util.flask.cache_check_headers() or "_refresh" in request.values,
|
||||
key=lambda: "view:{}".format(request.base_url))
|
||||
|
|
|
|||
Loading…
Reference in a new issue