Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lock extend should be able to take new timeout value #629

Closed
thomasst opened this issue Jun 20, 2015 · 2 comments
Closed

Lock extend should be able to take new timeout value #629

thomasst opened this issue Jun 20, 2015 · 2 comments

Comments

@thomasst
Copy link
Contributor

Instead of adding "additional time" to the lock, it should be possible to specify a new timeout for the lock. Consider the following use case:

while perform_operation(): # usually completes quickly, but should not take longer than N seconds
    lock.extend(N)

In this example, I'd want the lock to expire after no more than N seconds, regardless of how quickly the operation completes. With the current lock implementation this isn't possible. There should be a separate method or argument which indicates that the passed time is the new timeout value (as opposed to being added to the current timeout value).

@xush6528
Copy link

xush6528 commented Jun 30, 2016

I want it too!

Now I have to wrap the Lock class.

class MyLock(Lock):
    def __init__(self, *args, **kwargs):
        super(MyLock, self).__init__(*args, **kwargs)

    def expire(self, new_expire_time):
        """
        Reset expire time to an already acquired lock.

        ``new_expire_time`` can be specified as an integer or a float, both
        representing the number of seconds to add.
        """
        if self.local.token is None:
            raise LockError("Cannot extend an unlocked lock")
        if self.timeout is None:
            raise LockError("Cannot extend a lock with no timeout")
        return self.do_extend(new_expire_time)

    def do_expire(self, new_expire_time):
        pipe = self.redis.pipeline()
        pipe.watch(self.name)
        lock_value = pipe.get(self.name)
        if lock_value != self.local.token:
            raise LockError("Cannot extend a lock that's no longer owned")
        pipe.multi()
        pipe.pexpire(self.name, int(new_expire_time * 1000))

        try:
            response = pipe.execute()
        except WatchError:
            # someone else acquired the lock
            raise LockError("Cannot extend a lock that's no longer owned")
        if not response[0]:
            # pexpire returns False if the key doesn't exist
            raise LockError("Cannot extend a lock that's no longer owned")
        return True

Then

redis_client = Redis(...)
redis_client.lock(name, lock_class=MyLock)

@andymccurdy
Copy link
Contributor

This has been merged in d127929. It will go out to PyPI with the next version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants