-
Notifications
You must be signed in to change notification settings - Fork 30
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
unexpected ordering #35
Comments
Hello, Thanks for raising this, it's an interesting problem. By the sounds of the description your diagnosis in the third paragraph is probably correct. A I'm not quite sure what would have happened with the The guarantee that This is assuming that there's nothing else sending commands for the same key, of course. If this was intended to be used in a situation where Redis was shared by multiple processes all doing the same thing, you'd need to use Redis's transactional features: https://redis.io/topics/transactions which unfortunately aren't yet supported by Another alternative is to put the |
I tried an experiment of chaining two of the futures I'm using with |
Ah OK, I can see it now. This is an interesting edge-case. When the call to The solution for this would be drop lines 112 to 115, and instead of 116 do: iter_ok::<_, redis_async::error::Error>(events).for_each(move |event| get_dedup_future(conn.clone(), event)) This will make sure that the following An alternative would be to wrap the implementation of (I'm now thinking a future version of the library probably should have a Personally I prefer the first option, but whichever works best depends on the idioms of the wider application. |
I just stumbled on this solution in a slightly different form myself. Some background: the "add a future to the Vec" loop exists because I'd tried earlier to create a
This is a more verbose equivalent of what you have. It took me a bit to understand why this worked. To restate what you said: calling |
I'm having some unexpected results with a program using
redis_async
. For a series of items (structs with a "key" and "data" field), it does a RedisGET
and, depending on the result, possibly aSET
. The processing of earlier items in this sequence ought to affect the processing of later ones, but doesn't, until the next run of the program. The code is basically a simple de-duplication algorithm that only puts things in Redis if they don't exist or are different: It attempts toGET
each object in the series from Redis. If not found, or the value in Redis is different, it issues aSET
for the object. For identical objects it does nothing.Given a series of three identical objects, I'd expect the program to store the value for the first object, then do nothing for the remaining two. Instead, the code performs three
SET
operations, as if the initialSET
(or subsequent ones) had no effect. I've confirmed that theSET
s did indeed happen. I want the sequence to be (GET
->SET
),(GET
-NOOP
)->(GET
->NOOP
), but according to the traces I put in, the actual sequence isGET
,GET
,GET
,SET
,SET
,SET
. The requests are being pipelined in a way that ensures theGET
s complete before anySET
s do. So from the standpoint of the program, the searched for object doesn't exist in Redis. Of course, when you run the program again, the object is in Redis and it correctly identifies the objects as duplicates.My first attempt at this created a
Vec
of 3 futures and then usedfuture::join_all()
to return a combined set of futures. On reflection, this didn't seem right because it doesn't say anything about the order that things should happen. It seemed like it just launched all three concurrently (with the initialGET
s at the head of the queue). I also tried creating a "stream" of futures withfor_each()
, but that didn't change the order that things happened. Is there a way to somehow create an ordered sequence of "future chains" (meaning the (GET
->SET
, or possibly (GET
->NOOP
) such that those two things completes before the next "pair of operations" happens?The text was updated successfully, but these errors were encountered: