Merge branch 'fix/preemptiveUiCaching' into dev/preemptiveUiCachingWithUiPlugins

Conflicts:
	src/octoprint/server/__init__.py
	src/octoprint/server/views.py
This commit is contained in:
Gina Häußge 2015-11-24 18:44:05 +01:00
commit b3e6fe622d
3 changed files with 40 additions and 32 deletions

View file

@ -43,6 +43,7 @@ loginManager = None
pluginManager = None
appSessionManager = None
pluginLifecycleManager = None
preemptiveCache = None
principals = Principal(app)
admin_permission = Permission(RoleNeed("admin"))
@ -63,6 +64,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
@ -146,6 +148,7 @@ class Server():
global pluginManager
global appSessionManager
global pluginLifecycleManager
global preemptiveCache
global debug
from tornado.ioloop import IOLoop
@ -184,6 +187,7 @@ class Server():
printer = Printer(fileManager, analysisQueue, printerProfileManager)
appSessionManager = util.flask.AppSessionManager()
pluginLifecycleManager = LifecycleManager(pluginManager)
preemptiveCache = PreemptiveCache(os.path.join(self._settings.getBaseFolder("data"), "preemptive_cache_config.yaml"))
# setup access control
if self._settings.getBoolean(["accessControl", "enabled"]):
@ -208,7 +212,8 @@ class Server():
app_session_manager=appSessionManager,
plugin_lifecycle_manager=pluginLifecycleManager,
data_folder=os.path.join(self._settings.getBaseFolder("data"), name),
user_manager=userManager
user_manager=userManager,
preemptive_cache=preemptiveCache
)
def settings_plugin_inject_factory(name, implementation):
@ -476,7 +481,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()
@ -555,9 +560,6 @@ class Server():
Markdown(app)
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
@ -662,19 +664,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
@ -692,7 +691,7 @@ class Server():
else:
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))

View file

@ -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):

View file

@ -14,7 +14,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
@ -73,8 +73,9 @@ def index():
))
# finally decorate our view
return app.preemptive_cache.recorded(data=d,
unless=lambda: request.url_root in settings().get(["server", "preemptiveCache", "exceptions"]))(view)
return util.flask.preemptively_cached(cache=preemptiveCache,
data=d,
unless=lambda: request.url_root in settings().get(["server", "preemptiveCache", "exceptions"]))(view)
def get_cached_view(key, view, additional_key_data=None):
def cache_key():
@ -554,8 +555,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: "{}".format(request.base_url))