general: cache substitution variables in requests (#22107)

This commit is contained in:
Frédéric Péters 2018-02-25 14:14:27 +01:00
parent d686c0841f
commit 95651fc809
6 changed files with 47 additions and 2 deletions

View File

@ -359,6 +359,7 @@ def test_dispatch_auto(pub):
item.dispatch_type = 'automatic'
formdata = formdef.data_class()()
pub.substitutions.reset()
pub.substitutions.feed(formdata)
item.perform(formdata)
assert not formdata.workflow_roles
@ -375,21 +376,29 @@ def test_dispatch_auto(pub):
{'role_id': role2.id, 'value': 'bar'},
]
pub.substitutions.reset()
pub.substitutions.feed(formdata)
item.perform(formdata)
assert not formdata.workflow_roles
# no match
formdata.data = {'1': 'XXX'}
pub.substitutions.reset()
pub.substitutions.feed(formdata)
item.perform(formdata)
assert not formdata.workflow_roles
# match
formdata.data = {'1': 'foo'}
pub.substitutions.reset()
pub.substitutions.feed(formdata)
item.perform(formdata)
assert formdata.workflow_roles == {'_receiver': role1.id}
# other match
formdata.data = {'1': 'bar'}
pub.substitutions.reset()
pub.substitutions.feed(formdata)
item.perform(formdata)
assert formdata.workflow_roles == {'_receiver': role2.id}

View File

@ -14,6 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
import copy
import datetime
import time
import random
@ -1569,6 +1570,7 @@ class PageField(Field):
# backward compatibility. They are not added globally as they would
# interfere with the var_ prefixed variables used in dynamic jsonp
# fields. (#9786)
data = copy.copy(data)
data.update(live_data)
try:

View File

@ -29,7 +29,7 @@ from qommon import _
from qommon.storage import StorableObject, Intersects, Contains
import qommon.misc
from qommon.evalutils import make_datetime
from qommon.substitution import Substitutions
from qommon.substitution import Substitutions, invalidate_substitution_cache
from qommon.template import Template
from roles import Role
@ -290,6 +290,7 @@ class FormData(StorableObject):
if changed:
self.store()
@invalidate_substitution_cache
def store(self, *args, **kwargs):
# make sure the class set under the formdef name in the sys.modules
# namespaces is the exact one that was used when creating this

View File

@ -14,8 +14,19 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
from quixote import get_request
from quixote.html import htmltext, TemplateIO
def invalidate_substitution_cache(func):
def f(*args, **kwargs):
try:
return func(*args, **kwargs)
finally:
Substitutions.invalidate_cache()
return f
class Substitutions(object):
substitutions_dict = {}
dynamic_sources = []
@ -41,9 +52,11 @@ class Substitutions(object):
cls.dynamic_sources = []
cls.dynamic_sources.append(klass)
@invalidate_substitution_cache
def reset(self):
self.sources = []
@invalidate_substitution_cache
def feed(self, source):
if source is None:
# silently ignore a None source, this is for example useful when
@ -52,10 +65,22 @@ class Substitutions(object):
return
self.sources.append(source)
@classmethod
def invalidate_cache(cls):
request = get_request()
if hasattr(request, '_cache_context_variables'):
delattr(request, '_cache_context_variables')
def get_context_variables(self):
request = get_request()
d = getattr(request, '_cache_context_variables', None)
if d is not None:
return d
d = {}
for source in self.sources:
d.update(source.get_substitution_variables())
if request:
request._cache_context_variables = d
return d
@classmethod

View File

@ -24,6 +24,7 @@ import cPickle
from quixote import get_publisher
import qommon
from qommon.storage import _take, parse_clause as parse_storage_clause
from qommon.substitution import invalidate_substitution_cache
from qommon import get_cfg
import wcs.categories
@ -1185,6 +1186,7 @@ class SqlFormData(SqlMixin, wcs.formdata.FormData):
cur.close()
@guard_postgres
@invalidate_substitution_cache
def store(self):
sql_dict = {
'user_id': self.user_id,
@ -1508,6 +1510,7 @@ class SqlUser(SqlMixin, wcs.users.User):
self.roles = []
@guard_postgres
@invalidate_substitution_cache
def store(self):
sql_dict = {
'name': self.name,
@ -1691,6 +1694,7 @@ class TrackingCode(SqlMixin, wcs.tracking_code.TrackingCode):
id = None
@guard_postgres
@invalidate_substitution_cache
def store(self):
sql_dict = {
'id': self.id,

View File

@ -20,7 +20,7 @@ from qommon.storage import StorableObject
from qommon import get_cfg
import wcs.qommon.storage as st
from qommon.substitution import Substitutions
from qommon.substitution import Substitutions, invalidate_substitution_cache
class User(StorableObject):
_names = 'users'
@ -66,6 +66,10 @@ class User(StorableObject):
if changed:
self.store()
@invalidate_substitution_cache
def store(self, *args, **kwargs):
return super(User, self).store(*args, **kwargs)
@classmethod
def get_formdef(cls):
from admin.settings import UserFieldsFormDef