Skip to content

Commit

Permalink
fix: refresh connection of redis (#185)
Browse files Browse the repository at this point in the history
* wip: update connection property

* feat: Retry fetching value from Redis; return null if unsuccessful and log errors

* test: update redis cache test

* test: update tests

* refactor: update atribute name
  • Loading branch information
Luis-Henrique authored May 7, 2024
1 parent 673bef7 commit b86d24a
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 4 deletions.
35 changes: 32 additions & 3 deletions faster_sam/cache/redis_cache.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import logging
import os
from typing import Optional

from redis import Redis

from faster_sam.cache.cache_interface import CacheInterface

logger = logging.getLogger(__name__)

CACHE_TTL = int(os.getenv("FASTER_SAM_CACHE_TTL", 900))
CACHE_URL = os.getenv("FASTER_SAM_CACHE_URL", "")
Expand Down Expand Up @@ -58,6 +62,20 @@ def connection(self) -> Redis:

return self._connection

def reconnect(self) -> None:
"""
Reconnect to the Redis server.
This method is used to re-establish a connection to the Redis server
in case the connection is lost.
Returns
-------
None
"""
self.connection.disconnect()
self.connection.connect()

def set(self, key: str, value: str, ttl: int = CACHE_TTL) -> None:
"""
Set a value in the Redis cache.
Expand All @@ -77,9 +95,12 @@ def set(self, key: str, value: str, ttl: int = CACHE_TTL) -> None:
-------
None
"""
self.connection.set(key, value, ttl)
try:
self.connection.set(key, value, ttl)
except ConnectionError:
logger.info("Failed to connect to Redis server.")

def get(self, key: str) -> Optional[str]:
def get(self, key: str, attempts: int = 1) -> Optional[str]:
"""
Retrieve a value from the Redis cache.
Expand All @@ -94,4 +115,12 @@ def get(self, key: str) -> Optional[str]:
The value associated with the given key if it exists in the cache,
otherwise None.
"""
return self.connection.get(key)
try:
return self.connection.get(key)
except ConnectionError:
if attempts > 0:
self.reconnect()
return self.get(key, attempts - 1)

logger.info("Failed to connect to Redis server.")
return None
37 changes: 36 additions & 1 deletion tests/test_redis.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import unittest
from unittest import mock

from faster_sam.cache import redis_cache
from faster_sam.cache.cache_interface import CacheInterface

from faster_sam.cache.redis_cache import RedisCache


class FakeRedis(CacheInterface):
def __init__(self):
self._db = {}
self.connected = False

def disconnect(self) -> None:
self.connected = False

def connect(self) -> None:
self.connected = True

def set(self, key, value, ttl):
if isinstance(value, dict):
Expand All @@ -28,6 +35,7 @@ def setUp(self) -> None:

self.redis_patch = mock.patch("faster_sam.cache.redis_cache.Redis")
self.redis_mock = self.redis_patch.start()

self.redis_mock.from_url.return_value = FakeRedis()
self.key = "1234"

Expand All @@ -50,6 +58,33 @@ def test_cache(self):
self.assertIsNotNone(payload)
self.assertEqual(payload, "teste")

@mock.patch.object(RedisCache, "reconnect")
@mock.patch.object(FakeRedis, "set", side_effect=ConnectionError)
def test_set_cache_exception(self, mock_set, mock_reconnect):
cache = RedisCache()
cache.set("123", "teste", 900)

self.assertIsNone(cache.get("123"))
mock_set.assert_called_once()
mock_reconnect.assert_not_called()

@mock.patch.object(RedisCache, "reconnect")
@mock.patch.object(FakeRedis, "get", side_effect=ConnectionError)
def test_get_cache_exception(self, mock_get, mock_reconnect):
cache = RedisCache()
cache.set("123", "teste", 900)
response = cache.get("123")

self.assertIsNone(response)
self.assertEqual(mock_get.call_count, 2)
mock_reconnect.assert_called_once()

def test_reconnect(self):
cache = RedisCache()
cache.reconnect()

self.assertTrue(cache.connection.connected)

def test_cache_not_exists(self):
cache = RedisCache()
payload = cache.get("1234")
Expand Down

0 comments on commit b86d24a

Please sign in to comment.