Skip to content

Commit

Permalink
log error and skip caching if serializing a dictionary with non-str keys
Browse files Browse the repository at this point in the history
  • Loading branch information
matt-codecov committed Nov 14, 2024
1 parent 6d26b60 commit b6c6996
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 2 deletions.
22 changes: 20 additions & 2 deletions shared/helpers/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,22 @@
DEFAULT_TTL = 120


def attempt_json_dumps(value: Any) -> str:
def assert_string_keys(d: dict[Any, Any]) -> None:
for k, v in d.items():
if type(k) is not str:
raise TypeError(
f"Attempted to JSON-serialize a dictionary with non-string key: {k}"
)
if isinstance(v, dict):
assert_string_keys(v)

if isinstance(value, dict):
assert_string_keys(value)

return json.dumps(value)


def make_hash_sha256(o: Any) -> str:
"""Provides a machine-independent, consistent hash value for any object
Expand Down Expand Up @@ -104,12 +120,14 @@ def get(self, key: str) -> Any:

def set(self, key: str, ttl: int, value: Any):
try:
serialized_value = json.dumps(value)
serialized_value = attempt_json_dumps(value)
self.redis_connection.setex(key, ttl, serialized_value)
except RedisError:
log.warning("Unable to set cache on redis", exc_info=True)
except TypeError:
log.exception("Attempted to cache a type that is not JSON-serializable")
log.exception(
f"Attempted to cache a type that is not JSON-serializable: {value}"
)


class LogMapping(dict):
Expand Down
7 changes: 7 additions & 0 deletions tests/unit/helpers/test_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ def test_simple_redis_call_not_json_serializable(self):
redis_backend.set("normal_key", 120, unserializable)
assert redis_backend.get("normal_key") == NO_VALUE

def test_simple_redis_call_dict_with_int_keys(self):
redis_backend = RedisBackend(FakeRedis())

d = {"abcde": {1: [1, 2, 3], 2: [4, 5, 6]}}
redis_backend.set("normal_key", 120, d)
assert redis_backend.get("normal_key") == NO_VALUE


class TestCache(object):
def test_simple_caching_no_backend_no_params(self, mocker):
Expand Down

0 comments on commit b6c6996

Please sign in to comment.