perf: cache live access data during request (#46854)

This commit is contained in:
Frédéric Péters 2020-09-21 20:01:41 +02:00
parent e522d58dac
commit eff8a6cb48
2 changed files with 30 additions and 4 deletions

View File

@ -7,6 +7,7 @@ import sys
import shutil
import time
import mock
from django.utils import six
from quixote import cleanup
from quixote.http_request import Upload
@ -827,11 +828,19 @@ def test_lazy_formdata_live_item(pub):
assert context['form_var_foo_live_var_attr'] == 'attr2'
assert 'form_var_foo_live_var_attr' in context.get_flat_keys()
CardDef.wipe()
pub.get_request().live_card_cache = {}
context = pub.substitutions.get_context_variables(mode='lazy')
with pytest.raises(KeyError):
context['form_var_foo_live_name']
assert 'form_var_foo_live_var_attr' not in context.get_flat_keys()
# mock missing carddef to get call count
with mock.patch('wcs.carddef.CardDef.get_by_urlname') as get_by_urlname:
get_by_urlname.side_effect = KeyError
with pytest.raises(KeyError):
context['form_var_foo_live_name']
assert get_by_urlname.call_count == 1
with pytest.raises(KeyError): # repeated access, will go through cache
context['form_var_foo_live_name']
assert get_by_urlname.call_count == 1
assert 'form_var_foo_live_var_attr' not in context.get_flat_keys()
def test_lazy_formdata_queryset(pub, variable_test_data):

View File

@ -687,11 +687,28 @@ class LazyFieldVarStructured(LazyFieldVar):
def live(self):
if not (self._field.data_source and self._field.data_source.get('type', '').startswith('carddef:')):
raise AttributeError('live')
request = get_request()
if request:
# cache during request
cache_key = '%s-%s' % (self._field.data_source['type'], self.raw)
if not hasattr(request, 'live_card_cache'):
request.live_card_cache = {}
else:
carddata = request.live_card_cache.get(cache_key)
if carddata is not None:
# cached data
if isinstance(carddata, Exception):
raise carddata
return LazyFormData(carddata)
from wcs.carddef import CardDef
try:
carddef = CardDef.get_by_urlname(self._field.data_source['type'][8:])
carddata = carddef.data_class().get(self.raw)
if request:
request.live_card_cache[cache_key] = carddata
except KeyError:
if request:
request.live_card_cache[cache_key] = AttributeError('live')
raise AttributeError('live')
return LazyFormData(carddata)