Projet

Général

Profil

0002-misc-push-cache-of-JSON-content-in-get_json_from_url.patch

Benjamin Dauvergne, 09 décembre 2022 16:25

Télécharger (5,89 ko)

Voir les différences:

Subject: [PATCH 2/2] misc: push cache of JSON content in get_json_from_url
 (#39723)

It allows request_json_items and request_geojson_items to use the cache,
and cache is then also used in AutocompleteDirectory.
 wcs/api.py          |  8 +++++++-
 wcs/data_sources.py | 39 ++++++++++++++++++++-------------------
 2 files changed, 27 insertions(+), 20 deletions(-)
wcs/api.py
1187 1187

  
1188 1188
        if 'url' in info:
1189 1189
            named_data_source = None
1190
            cache_duration = 0
1190 1191
            if info.get('data_source'):
1191 1192
                named_data_source = NamedDataSource.get(info['data_source'])
1193
                cache_duration = named_data_source.cache_duration
1192 1194
            url = info['url']
1193 1195
            url += urllib.parse.quote(get_request().form.get('q', ''))
1194 1196
            url = sign_url_auto_orig(url)
1195 1197
            get_response().set_content_type('application/json')
1196
            entries = request_json_items(url, named_data_source and named_data_source.extended_data_source)
1198
            entries = request_json_items(
1199
                url,
1200
                named_data_source and named_data_source.extended_data_source,
1201
                cache_duration=cache_duration,
1202
            )
1197 1203
            if entries is not None:
1198 1204
                return json.dumps({'err': 0, 'data': entries})
1199 1205
            return json.dumps({'err': 1, 'data': []})
wcs/data_sources.py
241 241
                return str(option['id'])
242 242

  
243 243

  
244
def get_json_from_url(url, data_source=None, log_message_part='JSON data source', raise_request_error=False):
244
def get_json_from_url(
245
    url, data_source=None, log_message_part='JSON data source', raise_request_error=False, cache_duration=0
246
):
245 247
    url = sign_url_auto_orig(url)
246 248
    data_source = data_source or {}
247 249
    data_key = data_source.get('data_attribute') or 'data'
248 250
    geojson = data_source.get('type') == 'geojson'
249 251
    error_summary = None
250 252

  
253
    if cache_duration:
254
        cache_key = 'http-cache-%s' % force_str(hashlib.md5(force_bytes(url)).hexdigest())
255
        from django.core.cache import cache
256

  
257
        entries = cache.get(cache_key)
258
        if entries is not None:
259
            return entries
260

  
251 261
    try:
252 262
        entries = misc.json_loads(misc.urlopen(url).read())
253 263
        if not isinstance(entries, dict):
......
273 283
                data = data[key]
274 284
            if not isinstance(data.get(keys[-1]), list):
275 285
                raise ValueError('not a json dict with a %s list attribute' % data_key)
286
        if cache_duration:
287
            cache.set(cache_key, entries, cache_duration)
276 288
        return entries
277 289
    except misc.ConnectionError as e:
278 290
        error_summary = 'Error loading %s (%s)' % (log_message_part, str(e))
......
292 304
    return None
293 305

  
294 306

  
295
def request_json_items(url, data_source):
296
    entries = get_json_from_url(url, data_source)
307
def request_json_items(url, data_source, cache_duration=0):
308
    entries = get_json_from_url(url, data_source, cache_duration=cache_duration)
297 309
    if entries is None:
298 310
        return None
299 311
    data_key = data_source.get('data_attribute') or 'data'
......
321 333
    return items
322 334

  
323 335

  
324
def request_geojson_items(url, data_source):
325
    entries = get_json_from_url(url, data_source)
336
def request_geojson_items(url, data_source, cache_duration=0):
337
    entries = get_json_from_url(url, data_source, cache_duration=cache_duration)
326 338
    if entries is None:
327 339
        return None
328 340
    items = []
......
360 372

  
361 373

  
362 374
def _get_structured_items(data_source, mode=None, raise_on_error=False):
363
    cache_duration = 0
364

  
365 375
    if data_source.get('type') and data_source.get('type').startswith('carddef:'):
366 376
        # cards
367 377
        from wcs.carddef import CardDef
368 378

  
369 379
        return CardDef.get_data_source_items(data_source['type'])
370 380

  
381
    cache_duration = 0
371 382
    if data_source.get('type') not in ('json', 'jsonp', 'geojson', 'formula', 'wcs:users'):
372 383
        # named data source
373 384
        named_data_source = NamedDataSource.get_by_slug(data_source['type'])
......
482 493
        if hasattr(request, 'datasources_cache') and url in request.datasources_cache:
483 494
            return request.datasources_cache[url]
484 495

  
485
        if cache_duration:
486
            cache_key = 'data-source-%s' % force_str(hashlib.md5(force_bytes(url)).hexdigest())
487
            from django.core.cache import cache
488

  
489
            items = cache.get(cache_key)
490
            if items is not None:
491
                return items
492

  
493 496
        if geojson:
494
            items = request_geojson_items(url, data_source)
497
            items = request_geojson_items(url, data_source, cache_duration=cache_duration)
495 498
        else:
496
            items = request_json_items(url, data_source)
499
            items = request_json_items(url, data_source, cache_duration=cache_duration)
497 500
        if items is None:
498 501
            if raise_on_error:
499 502
                raise DataSourceError('datasource %s is unavailable' % url)
500 503
            return []
501 504
        if hasattr(request, 'datasources_cache'):
502 505
            request.datasources_cache[url] = items
503
        if cache_duration:
504
            cache.set(cache_key, items, cache_duration)
505 506
        return items
506 507
    return []
507 508

  
508
-