[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:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user