#33361 closed Bug (fixed)
Redis cache backend doesn't allow storing bool values
Reported by: | Jeremy Lainé | Owned by: | Jeremy Lainé |
---|---|---|---|
Component: | Core (Cache system) | Version: | 4.0 |
Severity: | Release blocker | Keywords: | |
Cc: | Nick Pope, Daniyal Abbasi | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
The following code raises an exception: redis.exceptions.DataError: Invalid input of type: 'bool'. Convert to a bytes, string, int or float first.
from django.core.cache import cache cache.set("foo", True)
This contradicts the documentation which states that any data type supported by pickle can be stored to the cache.
The root cause seems to be because instances of int
are special-cased and not send through pickle, but redis-py cannot send booleans to redis:
What was the rationale behind the int
special-case? django-redis
for instance consistently sends all data through pickle.
Change History (9)
comment:1 by , 3 years ago
Cc: | added |
---|---|
Description: | modified (diff) |
Severity: | Normal → Release blocker |
Triage Stage: | Unreviewed → Accepted |
follow-up: 3 comment:2 by , 3 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
Thanks for the reply and the link to the discussion. I'm assigning myself to the ticket as I'd be happy to prepare a patch and corresponding test.
Regarding the proposed fix, it feels like we're just moving the problem as I'd expect similar issues with an user-defined subclasses of int
. Would it be acceptable to do:
-
django/core/cache/backends/redis.py
diff --git a/django/core/cache/backends/redis.py b/django/core/cache/backends/redis.py index 16556b1ded..bbb0e0320d 100644
a b from django.utils.module_loading import import_string 11 11 12 12 class RedisSerializer(PickleSerializer): 13 13 def dumps(self, obj): 14 if isinstance(obj, int):14 if type(obj) is int: 15 15 return obj 16 16 return super().dumps(obj) 17 17
comment:3 by , 3 years ago
Replying to Jeremy Lainé:
Thanks for the reply and the link to the discussion. I'm assigning myself to the ticket as I'd be happy to prepare a patch and corresponding test.
Regarding the proposed fix, it feels like we're just moving the problem as I'd expect similar issues with an user-defined subclasses of
int
. Would it be acceptable to do:
django/core/cache/backends/redis.py
diff --git a/django/core/cache/backends/redis.py b/django/core/cache/backends/redis.py index 16556b1ded..bbb0e0320d 100644
a b from django.utils.module_loading import import_string 11 11 12 12 class RedisSerializer(PickleSerializer): 13 13 def dumps(self, obj): 14 if isinstance(obj, int):14 if type(obj) is int: 15 15 return obj 16 16 return super().dumps(obj) 17 17
Yes, looks good, a small comment could de helpful.
comment:4 by , 3 years ago
I've submitted a PR which includes a simple unit test on serialization. I checked the tests pass by running it locally with a configured Redis cache, I'm not sure if CI executes backend-specific tests though.
comment:6 by , 3 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Thanks for report! It should be enough to special-case
bool
, e.g.django/core/cache/backends/redis.py
:Would you like to prepare a patch?
We do this to have better atomicity of
incr()
anddecr()
operations (see discussion).