Search code examples
c#stackexchange.redis

Is using the FireAndForget flag inside a StackExchange.Redis transaction meaningful?


If I use CommandFlags.FireAndForget inside a transaction with StackExchange.Redis, does this flag actually do anything? Or does the transaction completion wait until the Fire and Forget command has completed anyhow?

Supplemental - is the fire and forget option purely within StackExchange.Redis, or is it something that's passed to the Redis server, so the Redis server returns a response before completion?

E.g.:

   var transaction = Database.CreateTransaction();

   transaction.StringSetAsync(key, value);
   transaction.KeyExpireAsync(key, timeToLive, CommandFlags.FireAndForget);

   await transaction.ExecuteAsync(); 
   // will transaction.ExecuteAsync return before the Key Expire command has completed
   // or wait for it to finish?

Solution

  • Firstly: if all you want to do is set a string value with expiration: forget about transactions - just use:

    await Database.StringSetAsync(key, value, timeToLive);
    

    Job done. This might use SET .. EX ... or SETEX ..., depending on the server version and other details, but is a single atomic redis operation.


    The F+F flag has no significance to the server at all; it is entirely a client-library detail. In the case of transactions, it will have zero effect on the actual bulk operation itself (caveat: unless the ExecuteAsync uses F+F) - the line:

    await transaction.ExecuteAsync();
    

    will operate as normal, with the same latencies etc. What is impacted is the result of the individual sub-operations, i.e.

    var a = transaction.Whatever(..., CommandFlags.FireAndForget)
    var b = transaction.WhateverElse(..., CommandFlags.FireAndForget);
    
    await transaction.ExecuteAsync();
    

    The results of a and b will not be calculated, and (I honestly can't recall without checking) a and b may even report as "completed" before the transaction has even been executed, simply as a result of being handed back the default/dummy task (with default result false in this case, since they are both Task<bool> operations and default(bool) is false.