Problems with cache.get_or_set behaviour

Skip to first unread message

Raphael Michel

Feb 28, 2016, 5:26:50 PM2/28/16

I just experienced the following behaviour and would like to ask for
your opinion whether I should file this as a bug or whether this is
intended behaviour. I today had the pleasure to work with a crashed
memcached deaemon that could not restart because of a permission
problem. In this case, django, using the backend
behaved as follows:

>>> cache.set("foo", "bar")
>>> cache.get("foo")

So it fails silently and all get calls will return None. That is
sensible behaviour if one does not want cache calls to raise
exceptions. However, when using the new get_or_set() method from Django
1.9, I got

>>> cache.get_or_set('foo', default='bar')

This really is suprising to me. For any reasonable usage I can think of,
I would expect get_or_set() to return the specified default value.

When looking at the implementation of BaseCache.get_or_set, one finds
that in the case of the value not existing, the value is saved
and returned as follows:

if val is None:
val = self.add(key, default, timeout=timeout, version=version)
if val:
return self.get(key, default, version)
return val

I assume that the last get() call is there to prevent a possible
race condition with other processes that is updating the key right
after our add statement.

However, if val is for some reason not evaluating to True, the result
of add() is being returned. add() is documented as returning True or
False and I don't think it makes any sense to return True/False from a
method that is expected to return a cached value or a default value.

I think we need a better behaviour of get_or_set() if add() fails but
I'm unsure how it exactly should look like, otherwise I would have
prepared a patch.


Tim Graham

Mar 7, 2016, 9:07:13 AM3/7/16
to Django developers (Contributions to Django itself)
A solution is proposed in It looks reasonable to me. Feel free to give your feedback there.
Reply all
Reply to author
0 new messages