0001-maelis-add-cache-on-family-data-48477.patch
passerelle/apps/maelis/models.py | ||
---|---|---|
18 | 18 |
from collections import defaultdict |
19 | 19 | |
20 | 20 |
from urllib.parse import urljoin |
21 | 21 | |
22 | 22 |
import zeep |
23 | 23 |
from zeep.wsse.username import UsernameToken |
24 | 24 |
from zeep.helpers import serialize_object |
25 | 25 | |
26 |
from django.core.cache import cache |
|
26 | 27 |
from django.db import models |
27 | 28 |
from django.utils import timezone |
28 | 29 | |
29 | 30 |
from django.utils.translation import ugettext_lazy as _ |
30 | 31 | |
31 | 32 |
from passerelle.base.models import BaseResource |
32 | 33 |
from passerelle.utils.api import endpoint |
33 | 34 |
from passerelle.utils.jsonresponse import APIError |
... | ... | |
133 | 134 |
return self.link_set.get(name_id=name_id) |
134 | 135 |
except Link.DoesNotExist: |
135 | 136 |
raise APIError('User not linked to family', err_code='not-found') |
136 | 137 | |
137 | 138 |
def get_family_data(self, family_id, school_year=None): |
138 | 139 |
if not school_year: |
139 | 140 |
# fallback to current year if not provided |
140 | 141 |
school_year = utils.get_default_school_year() |
142 |
cache_key = 'maelis-%s-%s' % (family_id, school_year) |
|
143 |
family_data = cache.get(cache_key) |
|
144 |
if family_data: |
|
145 |
return family_data |
|
146 | ||
141 | 147 |
family_data = serialize_object(self.call('FamilyService?wsdl', |
142 | 148 |
'readFamily', |
143 | 149 |
dossierNumber=family_id, |
144 | 150 |
schoolYear=school_year)) |
145 | 151 |
for child in family_data['childInfoList']: |
146 | 152 |
utils.normalize_person(child) |
153 |
cache.set(cache_key, family_data, 300) |
|
154 | ||
155 |
# register cache keys related to this family |
|
156 |
cache_meta_key = 'maelis-%s' % family_id |
|
157 |
cache_keys = cache.get(cache_meta_key) or [] |
|
158 |
if cache_key not in cache_keys: |
|
159 |
cache_keys.append(cache_key) |
|
160 |
cache.set(cache_meta_key, cache_keys, 300) |
|
161 | ||
147 | 162 |
return family_data |
148 | 163 | |
149 | 164 |
def get_invoices(self, regie_id, name_id): |
150 | 165 |
family_id = self.get_link(name_id).family_id |
151 | 166 |
return [utils.normalize_invoice(i) for i in self.call( |
152 | 167 |
'InvoiceService?wsdl', 'readInvoices', |
153 | 168 |
numDossier=family_id, codeRegie=regie_id)] |
154 | 169 | |
... | ... | |
293 | 308 |
for contact_param in ('phone', 'mobile', 'mail'): |
294 | 309 |
if contact_param in post_data: |
295 | 310 |
params['contact'][contact_param] = post_data[contact_param] |
296 | 311 | |
297 | 312 |
r = self.call('FamilyService?wsdl', 'updateCoordinate', |
298 | 313 |
numDossier=link.family_id, |
299 | 314 |
numPerson=personID, |
300 | 315 |
**params) |
316 | ||
317 |
# invalidate cache on family |
|
318 |
cache_meta_key = 'maelis-%s' % link.family_id |
|
319 |
for cache_key in cache.get(cache_meta_key) or []: |
|
320 |
cache.delete(cache_key) |
|
321 | ||
301 | 322 |
return serialize_object(r) |
302 | 323 | |
303 | 324 |
@endpoint( |
304 | 325 |
display_category=_('Invoices'), |
305 | 326 |
display_order=1, |
306 | 327 |
name='regie', |
307 | 328 |
perm='can_access', |
308 | 329 |
pattern=r'^(?P<regie_id>[\w-]+)/invoices/?$', |
tests/test_maelis.py | ||
---|---|---|
193 | 193 |
status_code=200, |
194 | 194 |
headers={'Content-Type': 'text/xml'} |
195 | 195 |
) |
196 | 196 |
Link.objects.create(resource=connector, family_id='3264', name_id='local') |
197 | 197 |
resp = app.get('/maelis/test/regie/1/invoice/3264-53186?NameID=local') |
198 | 198 |
assert resp.json['data'] |
199 | 199 |
assert resp.json['data']['label'] == 'FACTURATION SEPTEMBRE 2014' |
200 | 200 |
assert resp.json['data']['display_id'] == '53186' |
201 | ||
202 | ||
203 |
@mock.patch('passerelle.utils.Request.get') |
|
204 |
@mock.patch('passerelle.utils.Request.post') |
|
205 |
def test_invalidate_cache(mocked_post, mocked_get, family_service_wsdl, |
|
206 |
connector, app): |
|
207 |
mocked_get.return_value = mock.Mock(content=family_service_wsdl) |
|
208 |
mocked_post.side_effect = ( |
|
209 |
utils.FakedResponse(content=get_xml_file('readFamily.xml'), |
|
210 |
status_code=200, |
|
211 |
headers={'Content-Type': 'text/xml'}), |
|
212 |
utils.FakedResponse(content=get_xml_file('updateCoordinatesResponse.xml'), |
|
213 |
status_code=200, |
|
214 |
headers={'Content-Type': 'text/xml'}), |
|
215 |
utils.FakedResponse(content=get_xml_file('readFamily.xml'), |
|
216 |
status_code=200, |
|
217 |
headers={'Content-Type': 'text/xml'}), |
|
218 |
) |
|
219 | ||
220 |
assert Link.objects.count() == 0 |
|
221 |
Link.objects.create(resource=connector, family_id='3264', name_id='local') |
|
222 |
resp = app.get('/maelis/test/family-info?NameID=local') |
|
223 |
assert not resp.json['err'] |
|
224 |
family_data = resp.json['data'] |
|
225 |
assert mocked_post.call_count == 1 |
|
226 | ||
227 |
# cached data |
|
228 |
resp = app.get('/maelis/test/family-info?NameID=local') |
|
229 |
assert family_data == resp.json['data'] |
|
230 |
assert mocked_post.call_count == 1 |
|
231 | ||
232 |
# invalidate cache |
|
233 |
resp = app.post_json('/maelis/test/update-coordinates?NameID=local&personID=21293', |
|
234 |
params={'mail': 'foo@example.com'} |
|
235 |
) |
|
236 |
assert resp.content is not None |
|
237 |
assert mocked_post.call_count == 2 |
|
238 | ||
239 |
# no more cached data |
|
240 |
resp = app.get('/maelis/test/family-info?NameID=local') |
|
241 |
assert mocked_post.call_count == 3 |
|
201 |
- |