When need use await for batch.KeyExpireAsync(key, TimeSpan.FromSeconds(expiry)) and when not?
maomaomqiu opened this issue · 4 comments
Hi,
I use below to batch expire keys without TTL
IBatch batch = db.CreateBatch(); // IDatabase db
foreach (var key in list)
{
batch.KeyExpireAsync(key, time);
}
batch.Execute();
It works well, but I take a look a KeyExpireAsync, in some code path it is sync, in some code path it is async.
Also some code example use await batch.KeyExpireAsync(key, time)
I try to use await batch.KeyExpireAsync(key, time);
in my scenario, unluckily the later logic will never be hit
All a batch does is guarantee that all the commands within it are be sent over in one contiguous block to Redis without being mixed in with anything else from the client. I emphasize client here because it does not guarantee that Redis will not interleave other commands it receives from other clients in with the batch (to guarantee that you must use a transaction - though that has it's own set of nuances)
For your case here, I would hazard a guess that you do not need a batch, and that you'd just be better off pipelining these commands implicitly:
// execute KeyExpireAsync against all your keys, then await them all
await Task.WhenAll(list.Select(k => db.KeyExpireAsync(k, time)));
This is a very simplified example - there are caveats, e.g. if you are operating on thousands of keys you might want to paginate over them or do some command queuing to prevent timeouts, but generally you can just collect the tasks from dispatched async commands and await them all to allow the multiplexer to automagically pipeline them for you.
Thanks @slorello89 promptly reply for this question,
All a batch does is guarantee that all the commands within it are be sent over in one contiguous block to Redis without being mixed in with anything else from the client.
I am curious for that, so how it guarantees? Could you explain it more detail further? Greatly thanks!
@maomaomqiu, this library uses a multiplexer to send all commands, from any thread in the runtime, to Redis over a single socket (per Redis Server), when you use a batch, the commands are internally queued, and not executed until after you call Execute
when you call execute, the library will prevent any other command from being sent to Redis over that connection until all of the commands from the batch have been executed.
Thanks @slorello89, I will take a look at source code to know it more detailly! Very appreciate to your answer : )