add cache for connector endpoint (#24640)

This commit is contained in:
Emmanuel Cazenave 2018-06-20 10:56:22 +02:00
parent 2cc36d68aa
commit 86a91e41e1
4 changed files with 98 additions and 2 deletions

View File

@ -32,7 +32,8 @@ class endpoint(object):
description_get=None,
description_post=None,
example_pattern=None,
parameters=None):
parameters=None,
cache_duration=None):
self.perm = perm
self.methods = methods
self.serializer_type = serializer_type
@ -45,6 +46,7 @@ class endpoint(object):
}
self.example_pattern = example_pattern
self.parameters = parameters
self.cache_duration = cache_duration
def __call__(self, func):
func.endpoint_info = self

View File

@ -1,9 +1,11 @@
import datetime
import hashlib
import inspect
import json
from django.apps import apps
from django.conf.urls import url
from django.core.cache import cache
from django.core.exceptions import PermissionDenied
from django.contrib.auth import logout as auth_logout
from django.contrib.auth import views as auth_views
@ -332,7 +334,18 @@ class GenericEndpointView(GenericConnectorMixin, SingleObjectMixin, View):
'connector_payload': payload
})
return self.endpoint(request, **self.get_params(request, *args, **kwargs))
params = self.get_params(request, *args, **kwargs)
if request.method == 'GET' and self.endpoint.endpoint_info.cache_duration:
cache_key = hashlib.md5(
repr(self.get_object().slug) + repr(self.endpoint) + repr(params)).hexdigest()
result = cache.get(cache_key)
if result is not None:
return result
result = self.endpoint(request, **params)
if request.method == 'GET' and self.endpoint.endpoint_info.cache_duration:
cache.set(cache_key, result, self.endpoint.endpoint_info.cache_duration)
return result
def get(self, request, *args, **kwargs):
if self.endpoint.endpoint_info.pattern:

View File

@ -90,3 +90,11 @@ def mock_api_adresse_data_gouv_fr_search():
def mock_api_adresse_data_gouv_fr_reverse():
with HTTMock(api_adresse_data_gouv_fr_reverse):
yield None
@pytest.fixture
def endpoint_dummy_cache(monkeypatch):
from django.core.cache import get_cache
import passerelle.views
monkeypatch.setattr(
passerelle.views, 'cache', get_cache('django.core.cache.backends.dummy.DummyCache'))

View File

@ -19,6 +19,7 @@ from __future__ import unicode_literals
import os
import json
import random
import mock
import pytest
@ -173,6 +174,10 @@ class FakeConnectorBase(object):
def foo7(self, request, param1='a', param2='b', param3='c'):
pass
@endpoint(cache_duration=10)
def cached_endpoint(self, request):
pass
def test_endpoint_decorator():
connector = FakeConnectorBase()
@ -216,8 +221,76 @@ def test_endpoint_decorator():
assert connector.foo7.endpoint_info.description == 'foo7 get'
connector.foo7.endpoint_info.http_method = 'post'
assert connector.foo7.endpoint_info.description == 'foo7 post'
assert connector.foo7.endpoint_info.cache_duration is None
assert connector.cached_endpoint.endpoint_info.cache_duration == 10
def test_endpoint_description_in_template(app, db):
StubInvoicesConnector(slug='fake').save()
resp = app.get('/stub-invoices/fake/')
assert 'Get invoice details' in resp.text
def test_endpoint_cache(app, db, monkeypatch):
@endpoint(cache_duration=10, methods=['get', 'post'], pattern='^(?P<url_param>\w+)/$')
def randominvoice(obj, request, url_param, get_param=None):
return {'data': random.randint(0, pow(10, 12))}
monkeypatch.setattr(StubInvoicesConnector, 'randominvoice', randominvoice, raising=False)
connector = StubInvoicesConnector(slug='fake')
connector.save()
class TestCache(object):
def __init__(self):
self.d = dict()
self.get_calls = 0
self.set_calls = 0
def get(self, key):
self.get_calls += 1
return self.d.get(key)
def set(self, key, value, timeout):
self.set_calls += 1
self.d[key] = value
def delete(self, key):
del self.d[key]
cache = TestCache()
import passerelle.views
monkeypatch.setattr(passerelle.views, 'cache', cache)
resp1 = app.get('/stub-invoices/fake/randominvoice/url_param_value/?get_param=get_param_value')
assert cache.get_calls == 1
assert cache.set_calls == 1
resp2 = app.get('/stub-invoices/fake/randominvoice/url_param_value/?get_param=get_param_value')
assert cache.get_calls == 2
assert cache.set_calls == 1
assert resp1.json_body == resp2.json_body
resp3 = app.get(
'/stub-invoices/fake/randominvoice/url_param_value/?get_param=get_param_value'
'&apikey=somekey&timestamp=somestamp')
assert cache.get_calls == 3
assert cache.set_calls == 1
assert resp1.json_body == resp3.json_body
resp4 = app.get('/stub-invoices/fake/randominvoice/url_param_value/?get_param=other_value')
assert cache.get_calls == 4
assert cache.set_calls == 2
assert resp1.json_body != resp4.json_body
resp5 = app.get('/stub-invoices/fake/randominvoice/other_value/?get_param=get_param_value')
assert cache.get_calls == 5
assert cache.set_calls == 3
assert resp1.json_body != resp5.json_body
resp6 = app.post('/stub-invoices/fake/randominvoice/other_value/?get_param=get_param_value')
assert cache.get_calls == 5
assert cache.set_calls == 3
assert resp1.json_body != resp6.json_body