0001-atos-genesys-do-not-use-threads-29320.patch
passerelle/apps/atos_genesys/models.py | ||
---|---|---|
97 | 97 |
cache = utils.RowLockedCache( |
98 | 98 |
function=self.call_select_codifications, |
99 | 99 |
row=self, |
100 |
key_prefix='atos-genesys-codifications') |
|
100 |
key_prefix='atos-genesys-codifications', |
|
101 |
logger=self.logger) |
|
101 | 102 |
return cache() |
102 | 103 | |
103 | 104 |
@endpoint(name='codifications', |
... | ... | |
274 | 275 |
cache = utils.RowLockedCache( |
275 | 276 |
function=self.call_select_usager, |
276 | 277 |
row=link, |
277 |
key_prefix='atos-genesys-usager') |
|
278 |
key_prefix='atos-genesys-usager', |
|
279 |
logger=self.logger) |
|
278 | 280 |
dossier = cache(link.id_per) |
279 | 281 |
# build text as "id_per - prenom - no |
280 | 282 |
text_parts = [str(link.id_per), '-'] |
passerelle/apps/atos_genesys/utils.py | ||
---|---|---|
1 | 1 |
import time |
2 | 2 |
import six |
3 |
import threading |
|
4 | 3 |
from contextlib import contextmanager |
5 | 4 | |
6 | 5 |
from django.db import transaction |
7 | 6 |
from django.core.cache import cache |
8 | 7 | |
8 |
from passerelle.utils.jsonresponse import APIError |
|
9 | ||
9 | 10 |
DEFAULT_DURATION = 5 * 60 # 5 minutes |
10 | 11 | |
11 | 12 |
# keep data in cache for 1 day, i.e. we can answer a request from cache for 1 day |
... | ... | |
29 | 30 |
a thread, prevent multiple update using row locks on database models and |
30 | 31 |
an update cache key. |
31 | 32 |
''' |
32 |
def __init__(self, function, row=None, duration=DEFAULT_DURATION, key_prefix=None): |
|
33 |
def __init__(self, function, logger=None, row=None, duration=DEFAULT_DURATION, key_prefix=None):
|
|
33 | 34 |
self.function = function |
34 | 35 |
self.row = row |
35 | 36 |
self.duration = duration |
36 | 37 |
self.key_prefix = key_prefix or function.__name__ |
38 |
self.logger = logger |
|
37 | 39 | |
38 | 40 |
def _key(self, *args, **kwargs): |
39 | 41 |
keys = [] |
... | ... | |
59 | 61 |
cacheline = cache.get(key) |
60 | 62 |
if now - timestamp < self.duration: |
61 | 63 |
return cacheline['value'] |
62 |
updatekey = 'update-' + key |
|
63 |
update = cache.get(updatekey) |
|
64 |
if not update or (update['timestamp'] - now >= self.duration): |
|
65 |
cache.set(updatekey, {'timestamp': now}, CACHE_DURATION) |
|
66 | ||
67 |
def update(): |
|
68 |
value = self.function(*args, **kwargs) |
|
69 |
cache.set(key, {'value': value, 'timestamp': now}, CACHE_DURATION) |
|
70 |
cache.delete(updatekey) |
|
71 | ||
72 |
threading.Thread(target=update).start() |
|
64 |
try: |
|
65 |
value = self.function(*args, **kwargs) |
|
66 |
cache.set(key, {'value': value, 'timestamp': now}, CACHE_DURATION) |
|
67 |
except APIError as e: |
|
68 |
if self.logger: |
|
69 |
self.logger.error('failure to update cache %s', e) |
|
73 | 70 |
return cacheline['value'] |
74 | 71 |
else: |
75 | 72 |
value = self.function(*args, **kwargs) |
tests/test_atos_genesys.py | ||
---|---|---|
215 | 215 |
assert rlc() == 1 |
216 | 216 |
assert f.calls == 1 |
217 | 217 | |
218 |
# Check that cache update only launch one thread and f() is called only once again
|
|
218 |
# Check that with cache update f() is called only once again
|
|
219 | 219 |
freezer.move_to('2018-01-01 00:02:00') |
220 | 220 |
F.value = 2 |
221 | 221 |
counter = 0 |
222 |
- |