Add locks to ensure process safety

This commit is contained in:
ErikKalkoken 2023-08-02 15:58:36 +02:00
parent 1f55fbfccc
commit 20187cc73e

View File

@ -3,11 +3,12 @@
import logging import logging
from typing import Optional from typing import Optional
from app_utils.allianceauth import get_redis_client
from redis import Redis, RedisError from redis import Redis, RedisError
from django.core.cache import cache from django.core.cache import cache
from allianceauth.utils.cache import get_redis_client
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -56,7 +57,7 @@ class ItemCounter:
self._name = str(name) self._name = str(name)
self._minimum = minimum self._minimum = minimum
self._redis = redis if redis else get_redis_client() self._redis = get_redis_client_or_stub() if not redis else redis
@property @property
def _cache_key(self) -> str: def _cache_key(self) -> str:
@ -64,10 +65,11 @@ class ItemCounter:
def reset(self, init_value: int = 0): def reset(self, init_value: int = 0):
"""Reset counter to initial value.""" """Reset counter to initial value."""
if self._minimum is not None and init_value < self._minimum: with self._redis.lock(f"{self.CACHE_KEY_BASE}-reset"):
raise ValueError("Can not reset below minimum") if self._minimum is not None and init_value < self._minimum:
raise ValueError("Can not reset below minimum")
cache.set(self._cache_key, init_value, self.DEFAULT_CACHE_TIMEOUT) cache.set(self._cache_key, init_value, self.DEFAULT_CACHE_TIMEOUT)
def incr(self, delta: int = 1): def incr(self, delta: int = 1):
"""Increment counter by delta.""" """Increment counter by delta."""
@ -78,19 +80,20 @@ class ItemCounter:
def decr(self, delta: int = 1): def decr(self, delta: int = 1):
"""Decrement counter by delta.""" """Decrement counter by delta."""
if self._minimum is not None and self.value() == self._minimum: with self._redis.lock(f"{self.CACHE_KEY_BASE}-decr"):
return if self._minimum is not None and self.value() == self._minimum:
try: return
cache.decr(self._cache_key, delta) try:
except ValueError: cache.decr(self._cache_key, delta)
pass except ValueError:
pass
def value(self) -> Optional[int]: def value(self) -> Optional[int]:
"""Return current value or None if not yet initialized.""" """Return current value or None if not yet initialized."""
return cache.get(self._cache_key) return cache.get(self._cache_key)
def get_redis_client_or_stub(): def get_redis_client_or_stub() -> Redis:
"""Return AA's default cache client or a stub if Redis is not available.""" """Return AA's default cache client or a stub if Redis is not available."""
redis = get_redis_client() redis = get_redis_client()
try: try: