-
Notifications
You must be signed in to change notification settings - Fork 23.5k
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
Delay *SUBSCRIBE inside transactions #9928
base: unstable
Are you sure you want to change the base?
Conversation
3ea80e5
to
ea4fa39
Compare
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 wonder if anyone today is doing a multi-exec on a bunch of subscribes. I think a better solution would be to continue allowing subscribe in a multi-exec but deferring all of the published messages to the end. That should fix the resp corruption. @oranagra thoughts?
considering that the default for redis-py We did recently add some logic to defer client side tracking invalidation messages to after EXEC responses, maybe that's something we need to do for PUBLISH as well, (even regardless of whether SUBSCRIBE was issues in the transaction or not). @itamarhaber are you aware of any other considerations? |
ea4fa39
to
2462f57
Compare
Given redis-py's default, and the possible existence of this pattern in the wild regardless, I'd hate breaking it by denying/reordering. Per Oran's suggestion, deferring pushed PUBLISHed messages until after EXEC makes sense to me and shouldn't harm anyone (unless they dug that hole intentionally, in which case they deserve it). |
Ok, @joshleeb given the consensus seems to be against this suggestion, despite what salvatore wrote, do you mind updating this PR so that we defer message publishing until the end of the subscribe? This is probably a more complex change, so no worries if you don't want to take it. |
Yep happy to give it a shot 👍
It appears to me that this change was made in #9422. Is this the PR being referred to? Related to deferring
Is this something we want to change as well? That is, in |
yes
well, if we change that, maybe there's no need to defer the publish for later. there are already some checks in |
Agree with Oran, let's create a new wrapper around "call" that performs the common logic, that seems like a better solution. |
there is another problem that can be resolved by a similar fix: #9993 |
If this (deferring effects of commands until exec) is the start of a trend, then perhaps CONFIG SET should also be deferred too? (mainly for consistency, not that it's needed now that we have multi-config set). |
@joshleeb You still taking a look into this? |
This change extracts checks that are common to call sites of `call` into a wrapper function, and updates the callers to use the wrapper. Initially it contains a check to ensure that only allowed commands are called when in the context of `CLIENT_PUBSUB`.
2462f57
to
a24ce3a
Compare
Yep, sorry for the delay. I’ve updated the PR to add a I was struggling to test this by adding to the existing unit tests as they seem to reject calling SUBSCRIBE in a MULTI, as with the redis-cli. So I have written a small script to confirm the above. Test scriptimport socket
def msg(commands):
cs = commands.split(' ')
ms = ['*' + str(len(cs))]
for s in cs:
ms.append('$' + str(len(s)))
ms.append(s)
return '\r\n'.join(ms) + '\r\n'
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('127.0.0.1', 6379))
for c in ['multi', 'subscribe foo', 'publish foo asdf', 'exec']:
sock.send(msg(c))
parts = sock.recv(1024).split('\r\n')
print(c)
print(list(filter(None, parts))) Which produced the output
As for pulling out other common checks, I’m happy to do more in this PR or in follow ups. Another commonality which has been mentioned is ACL checks. Though with these I have opted not to pull that out as (in |
@joshleeb It has been lingering long time without a review. Sorry about that and thank you for this fix! |
@ranshid have you considered this #9928 (comment) ? |
@oranagra I also looked at #9928 but I think this will not break the current clients running many subscriptions since it is O.K to perform more subscribes when in subscribed mode. |
not sure you saw the exact comment i referred to. |
I think I understand that. I think that supporting ill handling of some clients is no reason to invest in supporting it, much more that the same clients will probably break or produce some other wrong behavior running other commands (like blocking commands) in that pipeline. I understand redis-py specifically can disable transactions for pipelines |
Yep still happy to work on this. I'll aim to dive back into it this week. |
|
This change updates the Redis server to deny
(P)SUBSCRIBE
commands when attempting to execute inside a transaction.Closes #2967