mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-07-09 20:40:17 +02:00
Add locks to ensure process safety
This commit is contained in:
parent
1f55fbfccc
commit
20187cc73e
@ -3,11 +3,12 @@
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from app_utils.allianceauth import get_redis_client
|
||||
from redis import Redis, RedisError
|
||||
|
||||
from django.core.cache import cache
|
||||
|
||||
from allianceauth.utils.cache import get_redis_client
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -56,7 +57,7 @@ class ItemCounter:
|
||||
|
||||
self._name = str(name)
|
||||
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
|
||||
def _cache_key(self) -> str:
|
||||
@ -64,10 +65,11 @@ class ItemCounter:
|
||||
|
||||
def reset(self, init_value: int = 0):
|
||||
"""Reset counter to initial value."""
|
||||
if self._minimum is not None and init_value < self._minimum:
|
||||
raise ValueError("Can not reset below minimum")
|
||||
with self._redis.lock(f"{self.CACHE_KEY_BASE}-reset"):
|
||||
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):
|
||||
"""Increment counter by delta."""
|
||||
@ -78,19 +80,20 @@ class ItemCounter:
|
||||
|
||||
def decr(self, delta: int = 1):
|
||||
"""Decrement counter by delta."""
|
||||
if self._minimum is not None and self.value() == self._minimum:
|
||||
return
|
||||
try:
|
||||
cache.decr(self._cache_key, delta)
|
||||
except ValueError:
|
||||
pass
|
||||
with self._redis.lock(f"{self.CACHE_KEY_BASE}-decr"):
|
||||
if self._minimum is not None and self.value() == self._minimum:
|
||||
return
|
||||
try:
|
||||
cache.decr(self._cache_key, delta)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def value(self) -> Optional[int]:
|
||||
"""Return current value or None if not yet initialized."""
|
||||
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."""
|
||||
redis = get_redis_client()
|
||||
try:
|
||||
|
Loading…
x
Reference in New Issue
Block a user