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

Update behavior of lock to behave closer to redis lock #216

Conversation

taylor-cedar
Copy link

I updated a project to use fakeredis and noticed some tests failing because the fakeredis lock implementation doesn't actually behave like the redis lock. If you create 2 locks with the same key, it doesn't actually fail to acquire the lock.

I added more tests and updated the implementation to handle multiple locks on the same key.

fakeredis.py Outdated
if can_acquire:
self.redis.set(self.name, self.id, ex=self.timeout)
elif blocking:
raise ValueError('fakeredis can\'t do blocking locks')
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally had an implementation to sleep and wait for the lock to be released, but eventually changed it to an error because blocking would likely wait forever or until the blocking_timeout. In either case I think it's an error and it's better to expose an exception instead of an infinite wait.

@taylor-cedar taylor-cedar force-pushed the make-fakelock-behave-closer-to-redis-lock branch from 924ca01 to 6fc7375 Compare September 17, 2018 21:09
@coveralls
Copy link

coveralls commented Sep 17, 2018

Coverage Status

Coverage increased (+98.4%) to 98.432% when pulling 4a24a1f on cedar-team:make-fakelock-behave-closer-to-redis-lock into b87e885 on jamesls:master.

@taylor-cedar taylor-cedar force-pushed the make-fakelock-behave-closer-to-redis-lock branch from 6fc7375 to 1ae9c12 Compare September 17, 2018 21:17
Copy link
Collaborator

@bmerry bmerry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! From a quick glance this looks good, but I'll need to come back to this in a few weeks when I'm planning to do some overhaul on fakeredis for thread safety. At present this won't be thread-safe (which is something a lock really should be) because the interactions with fakeredis functions it uses aren't thread-safe.

@taylor-cedar
Copy link
Author

taylor-cedar commented Sep 18, 2018

@bmerry Yes, this definitely isn't thread safe (as you said), but it wasn't before anyways. Can you merge it in and make it a minor version release for now? This isn't making anything worse and it fixes several issues that currently exist.

Thread safety is something that is important, but it seems outside the scope of this PR.

@bmerry
Copy link
Collaborator

bmerry commented Sep 18, 2018

The old code used threading.Lock, so it looks like it was thread-safe, as long as you used the same Lock object across threads.

@taylor-cedar
Copy link
Author

@bmerry Yes the original code was thread safe because it didn't really do any locking at all. It was basically a noop. I guess this could cause random issues if used in a threading environment. I added code to make it thread safe

@bmerry
Copy link
Collaborator

bmerry commented Sep 18, 2018

Thanks, I'll try to find some time this week to review this.

@taylor-cedar
Copy link
Author

taylor-cedar commented Sep 18, 2018

Thanks! I think the correct long term change here is to use redis.lock.Lock instead of a custom lock implementation. The default redis Lock does not rely on the redis server at all. I attempted to use it, but I ran into a different bug with watch. If you modify a key after a pipeline.watch from the same client it throws a redis.WatchError which isn't correct, it should ignore changes from the current client. I will create an issue for that bug.

@bmerry
Copy link
Collaborator

bmerry commented Sep 18, 2018

Thanks. My first thought when I looked at what redis.lock.Lock is the same as yours i.e. that once fakeredis does everything else right we can just reuse it.

@bmerry
Copy link
Collaborator

bmerry commented Sep 20, 2018

I've started a branch called "thread-safe" where I'm working on thread safety, and I've also replaced _Lock with a copy of redis.lock.Lock plus a few bug fixes. Give it a try and let me know if it works for your use case. I may also borrow some tests from this PR still.

bmerry added a commit that referenced this pull request Sep 25, 2018
Took a few tests from #216.
@bmerry
Copy link
Collaborator

bmerry commented Sep 25, 2018

I'm closing this because I've put in an implementation that's a copy of redis-py's plus bug fixes, and also taken some of your unit tests (thanks). Let me know if there are still issues.

@bmerry bmerry closed this Sep 25, 2018
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 this pull request may close these issues.

None yet

3 participants