Skip to content

"error: integer out of range for 'L' format code" due to timeout=0 #48

Open
@hheimbuerger

Description

@hheimbuerger

I'm using django-bmemcached and python-binary-memcached with django-brake for rate limiting.

Occasionally, I'm getting the following exception:

  File "/app/.heroku/python/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response 
    response = wrapped_callback(request, *callback_args, **callback_kwargs) 
  File "/app/.heroku/python/lib/python2.7/site-packages/brake/decorators.py", line 87, in _wrapped 
    _backend.count(func_name, request, ip, field, period) 
  File "/app/.heroku/python/lib/python2.7/site-packages/brake/backends/cachebe.py", line 65, in count 
    cache.set(key, (count, expiration), timeout=int(expiration - time.time())) 
  File "/app/.heroku/python/lib/python2.7/site-packages/django/core/cache/backends/memcached.py", line 91, in set 
    if not self._cache.set(key, value, self.get_backend_timeout(timeout)): 
  File "/app/.heroku/python/lib/python2.7/site-packages/bmemcached/client.py", line 161, in set 
    returns.append(server.set(key, value, time)) 
  File "/app/.heroku/python/lib/python2.7/site-packages/bmemcached/protocol.py", line 506, in set 
    return self._set_add_replace('set', key, value, time) 
  File "/app/.heroku/python/lib/python2.7/site-packages/bmemcached/protocol.py", line 477, in _set_add_replace 
    time, str_to_bytes(key), value)) 
error: integer out of range for 'L' format code 

It turns out that the problem is django-bmemcached passing a value of -1 as the argument timeout to python-binary-memcached. The latter tries to pack this as an L (unsigned long) into the struct, which of course fails for -1.

The -1 comes from the following code in BaseMemcachedCache.get_backend_timeout():

elif int(timeout) == 0:
    # Other cache backends treat 0 as set-and-expire. To achieve this
    # in memcache backends, a negative timeout must be passed.
    timeout = -1

The code before that indicates that it occures when an entry is set the moment it expires:

cache.set(key, (count, expiration), timeout=int(expiration - time.time()))

According to the docs, a timeout of 0 for cache.set() is valid and won't cache the value. However, that's apparently not how python-binary-memcached works.

Here I get a bit lost, just starting to use these libraries for the first time. I'm already pretty confused which code comes from which library. Can you help me out?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions