Projet

Général

Profil

0001-maelis-add-cache-on-family-data-48477.patch

Nicolas Roche, 25 novembre 2020 15:12

Télécharger (5,91 ko)

Voir les différences:

Subject: [PATCH] maelis: add cache on family data (#48477)

 passerelle/apps/maelis/models.py | 21 ++++++++++++++++
 tests/test_maelis.py             | 41 ++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)
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
-