gregoriusxu / booksleeve

Automatically exported from code.google.com/p/booksleeve
Other
0 stars 0 forks source link

Strange behavior using CancellationToken with Task.Wait #39

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. Using a connection, perform a blocking BLPOP with no time out (empty list to 
begin with)
2. Wait on this task using task.Wait(cancelToken)
3. Signal the Cancellation Token to Cancel() so that the task.Wait returns
4. Insert something into the list
5. Run the BLPOP command again, this time with a 1 second timeout
6. Notice via Redis MONITOR that the BLPOP was executed
7. Notice the returned result from Step 5 is empty/nothing
8. Notice that the list has been emptied (the item was popped off the list)
9. The popped item has been lost

What is the expected output? What do you see instead?
I would have expected the second BLPOP command to succeed.

I can understand that perhaps because the first BLPOP (that was cancelled) is 
still actually in-progress (and you can't cancel a Redis command this way?) 
that this is not going to work properly.

What version of the product are you using? On what operating system?
redis 2.6.8-pre2 (Windows)
Booksleeve 1.3.12

Please provide any additional information below.
Ideally I want this feature to work so I can block forever, or until my calling 
code decides it doesn't want to be blocking anymore (eg, give up), as opposed 
to using a pre-set timeout.

If this is not possible using cancellation tokens, perhaps Booksleeve should 
raise an error to indicate this is impossible, instead of this strange behavior.

Cheers

Original issue reported on code.google.com by phpla...@gmail.com on 3 Apr 2013 at 12:28

GoogleCodeExporter commented 8 years ago
Indeed. The message was sent to redis, regardless of what you do back in the 
client. There is no "actually, cancel that" in redis, so at the server-end the 
connection is going to block on either the timeout or a value to return. When a 
response comes back, it is still the response to that original request, no 
matter what you've done in the interim (in most cases, the next command is 
going to be something with a completely different result pattern) - so it can't 
say "oh, never mind - I'll give that reply to the next task" - that makes no 
sense.

As for BookSleeve raising an error: it simply doesn't have that option 
available. The task API is the task API. It can't change how it works. If you 
do something that isn't sensible, then bad things will happen.

Ultimately, the fundamental issue here is that what you want simply can't be 
supported on a redis connection. You could poll with a short timeout repeatedly 
- for example 1 second. But frankly I usually advise *against* using the 
blocking calls - they are antithetical to a multiplexer. My preferred pattern 
here would be to subscribe to a "here be data" channel, with a callback that 
uses a non-blocking fetch. Then publish a message to that channel when you 
insert data.

Original comment by marc.gravell on 3 Apr 2013 at 7:10

GoogleCodeExporter commented 8 years ago

Original comment by marc.gravell on 20 Mar 2014 at 12:10