Skip to content

Instantly share code, notes, and snippets.

@sunetos
Created August 3, 2010 15:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sunetos/506541 to your computer and use it in GitHub Desktop.
Save sunetos/506541 to your computer and use it in GitHub Desktop.
import redis
from contextlib import contextmanager
@contextmanager
def redisLock(r, key):
'''
Acquire a lock on a particular key (makes a new mutex key).
This is not meant for very high concurrency, just to avoid
data corruption in simple cases.
'''
tries = 15
lockKey = '%s-mutex' % (key)
locked = 0
for i in range(tries):
locked = r.setnx(lockKey, 1)
if not locked:
time.sleep(0.1)
else: break
if not locked: # Assume a crash or deadlock
r.set(lockKey, 1)
yield
r.delete(lockKey)
def setListItemIndex(r, key, oldIndex, newIndex):
''' Set the index of any redis list item efficiently. '''
with redisLock(r, key):
listSize = r.llen(key)
pipe = r.pipeline()
maxIndex = listSize - 1
queueKey = '%s-queue' % (key)
targetKey = '%s-target' % (key)
# First half: shuffle everything out of the list
for i in range(oldIndex, maxIndex):
pipe.rpoplpush(key, queueKey)
pipe.rpoplpush(key, targetKey)
for i in range(oldIndex):
pipe.rpoplpush(key, queueKey)
# Second half: put back in the list, in the new order
for i in range(newIndex, maxIndex):
pipe.rpoplpush(queueKey, key)
pipe.rpoplpush(targetKey, key)
for i in range(newIndex):
pipe.rpoplpush(queueKey, key)
pipe.execute()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment