[FIX] website: invalide cache page with classic ormcache invalidation

To avoid to manually invalid the lru cache and probably miss some place
(assets, website menu, qweb view, website, company, ...) we use the classic
cache.

Courtesy of @rco-odoo for the help and review

closes odoo/odoo#56744

X-original-commit: 98e12901c97a67dc87f21647473754cd6f384d4a
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
This commit is contained in:
Jeremy Kersten
2020-08-28 14:54:11 +00:00
parent 578ce5261b
commit 96bc3d4fff
2 changed files with 22 additions and 16 deletions
+4 -16
View File
@@ -19,7 +19,6 @@ from odoo import registry, SUPERUSER_ID
from odoo.http import request
from odoo.tools.safe_eval import safe_eval
from odoo.osv.expression import FALSE_DOMAIN
from odoo.tools.lru import LRU
from odoo.addons.http_routing.models.ir_http import ModelConverter, _guess_mimetype
from odoo.addons.portal.controllers.portal import _build_url_w_params
@@ -70,7 +69,6 @@ class Http(models.AbstractModel):
@classmethod
def clear_caches(cls):
super(Http, cls)._clear_routing_map()
cls.clear_cached_pages()
return super(Http, cls).clear_caches()
@classmethod
@@ -243,10 +241,6 @@ class Http(models.AbstractModel):
installed = request.registry._init_modules | set(odoo.conf.server_wide_modules)
return mods + [mod for mod in installed if mod.startswith('website')]
@classmethod
def clear_cached_pages(cls):
cls._cached_pages = LRU(1024)
@classmethod
def _serve_page(cls):
req_page = request.httprequest.path
@@ -268,22 +262,17 @@ class Http(models.AbstractModel):
and request.httprequest.method == "GET"
and request.env.user._is_public() # only cache for unlogged user
and 'nocache' not in request.params # allow bypass cache / debug
and not request.session.debug
and len(cache_key) and cache_key[-1] is not None # nocache via expr
):
need_to_cache = True
if not hasattr(cls, '_cached_pages'):
cls.clear_cached_pages() # init LRU
# use cached version
try:
r = cls._cached_pages[cache_key]
r = page._get_cache_response(cache_key)
if r['time'] + page.cache_time > time.time():
response = werkzeug.Response(r['content'], mimetype=r['contenttype'])
response._cached_template = r['template']
response._cached_page = page
return response
else:
cls._cached_pages[cache_key]
except KeyError:
pass
@@ -295,13 +284,12 @@ class Http(models.AbstractModel):
if need_to_cache and response.status_code == 200:
r = response.render()
cls._cached_pages[cache_key] = {
page._set_cache_response(cache_key, {
'content': r,
'contenttype': response.headers['Content-Type'],
'time': time.time(),
'template': getattr(response, 'qcontext', {}).get('response_template')
}
})
return response
return False
+18
View File
@@ -201,6 +201,7 @@ class Page(models.Model):
def write(self, vals):
if 'url' in vals and not vals['url'].startswith('/'):
vals['url'] = '/' + vals['url']
self.clear_caches() # write on page == write on view that invalid cache
return super(Page, self).write(vals)
def get_website_meta(self):
@@ -215,3 +216,20 @@ class Page(models.Model):
if self.cache_key_expr: # e.g. (request.session.geoip.get('country_code'),)
cache_key += safe_eval(self.cache_key_expr, {'request': req})
return cache_key
def _get_cache_response(self, cache_key):
""" Return the cached response corresponding to ``self`` and ``cache_key``.
Raise a KeyError if the item is not in cache.
"""
# HACK: we use the same LRU as ormcache to take advantage from its
# distributed invalidation, but we don't explicitly use ormcache
return self.pool._Registry__cache[('website.page', _cached_response, self.id, cache_key)]
def _set_cache_response(self, cache_key, response):
""" Put in cache the given response. """
self.pool._Registry__cache[('website.page', _cached_response, self.id, cache_key)] = response
# this is just a dummy function to be used as ormcache key
def _cached_response():
pass