add cache for connector endpoint (#24640)
This commit is contained in:
parent
2cc36d68aa
commit
86a91e41e1
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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'))
|
||||
|
|
|
@ -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×tamp=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
|
||||
|
|
Loading…
Reference in New Issue