-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Fix the watch command bugs for the cluster client #1255
Conversation
@@ -174,7 +174,7 @@ def version | |||
def with_acl | |||
admin = _new_client | |||
admin.acl('SETUSER', 'johndoe', 'on', | |||
'+ping', '+select', '+command', '+cluster|slots', '+cluster|nodes', | |||
'+ping', '+select', '+command', '+cluster|slots', '+cluster|nodes', '+readonly', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This permission may be needed. I don't know why it becomes needed since when. Some cases became failure in the ACL test.
707b0fb
to
65ac655
Compare
Fiber.yield | ||
end | ||
|
||
redis.watch('{key}1', '{key}2') do |tx| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this is the right interface that redis-cluster-client/redis-clustering should be exposing.
The normal redis-rb client interface looks like this:
redis.watch('{key}1', '{key}2') do
redis.get('{key}1')
redis.get('{key}2')
# Make some decision about what to do based on the value of these keys
redis.multi do |tx|
tx.set('{key}1', 'new_v1')
tx.set('{key}2', 'new_v2')
end
end
The differences are...
watch
does not actually yield anything (EDIT: it yields self but there are plenty of documented examples where the yielded value is ignored)- A transaction is not actually started unless
multi
is called
Would you like me to put up a different pair of PR's (one here, one in redis-cluster-client) to try and show how I think we could implement it in a compatible way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my implementation, the block is finally passed to the redis-cluster-client gem. I think the redis-cluster-client gem should not be complex in excess due to the redis gem. I think the transaction feature is quite different between standalone and cluster. But of course, I think the other approaches are welcome.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I can put most of the "hacking"/complexity in redis-clustering, but keep an interface in redis-cluster-client that actually makes sense in cluster mode.
Basically, redis-clustering is the "adapter" that takes the redis-cluster-client interface and makes it fit the redis-rb API pattern. That seems to make the most sense to me.
Let me try and get a couple of PR's up today :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@supercaracal what do you think about this approach? #1256 and redis-rb/redis-cluster-client#339
Basically, exposing the OptimisticLocking
object from a dedicated #watch
API on the redis-cluster-client side and then redis-rb makes that state implicit through the @active_watcher
ivar.
Sorry to be a pain here, but I really do want to ask whether this is actually the right interface @supercaracal @byroot This PR defines an interface for watch where the client code looks like
but, ordinary not-clustered redis-rb watches look like
There are a few problems with what has been merged in my opinion:
It requires a bit more support on the cluster-client side, but I believe the two PR's I mentioned above provide an alternative to this interface which resolves these problems and provides a better experience for users of both redis-rb/redis-cluster-client and also redis-cluster-client alone:
WDYT? Could this be revisited? |
@supercaracal is the redis cluster maintainer, I'm merely merging because I'm not admin of the repo so I can't really officialize this. I have 0 interest in Redis cluster and I trust @supercaracal to maintain it. |
The redis gem of version As you said, it broke compatibility between standalone and cluster mode, but there is a trade-off for the simplicity. I said repeatedly, the redis-cluster-client gem shouldn't be affected excessively by the redis-clustering gem. Also, I think it shouldn't be messed up with its code and design. If you desire the same interface between standalone and cluster in the transaction feature, I think it should be implemented by the redis-clustering gem or your own adapter. At least, I don't have a plan to change the interface of the redis-cluster-client gem related to the transaction feature except any bugs. |
But it's not just about not being the same as redis-clustering. The redis-clustering design is the way it is because that's the shape it has to be in in order to support workflows like WATCH-then-UNWATCH or WATCH-then-WATCH-again like I said here:
These are not esoteric use-cases, a primary purpose of Redis's WATCH API is to enable mixing application logic with Redis reads and then conditionally perform an atomic sequence of writes after that.
But you closed this option off by designing
This isn't possible (without gratuitious amounts of
In my humble opinion... the client library of a popular open-source database should support the full range of operations that the underlying database supports. That's worth a small amount of internal complexity in the gem. |
In the redis-cluster-client side, it's already the same interface between the redis-client gem and the redis-cluster-client gem. So I don't think any additional implementation is needed. |
0.7.11
.