Search code examples
c#cachingredisservicestackservicestack.redis

C# ServiceStack.Redis SetAll with expire


First, a link to the library: ServiceStack.Redis

now, Im working on some generic cache mechanism which supports, for now, in 4 methods:

Put, Get, PutMany, GetMany

Problem is, whenever I want to insert numerous records, I dont have an option (visible to me) to add an expiration, unlike Put - where I can.

The code is pretty streight forward:

public void PutMany(ICollection<T> items)
{
    TimeSpan expiration = GetExpiration();
    DateTime expire = DateTime.UtcNow.Add(expiration);

    Dictionary<string, CachedItem<T>> dict = new Dictionary<string, CachedItem<T>>();
    foreach (T item in items)
    {
        CachedItem<T> cacheItem = new CachedItem<T>(item, expire);

        if (!dict.ContainsKey(cacheItem.Id))
            dict.Add(cacheItem.Id, cacheItem);
    }

    // Store item in cache
    _client.SetAll(dict);
}

the model CachedItem<T> is mine, just imagine it as some sort of an object.

As you can see, I dont have an option of setting the expiration. Is there a way (besides inserting them 1 by 1 using _client.Set()) to achieve this?

TIA.

P.S

I know I can store all records in a list or an hash, I dont want that all the records will have a single expiration date (wrong, and can cause very serious performance issues whenever they expire)


Solution

  • Redis does not have any command that will let you set an expiry with a bulk insert nor does any of its Expire commands allow you to apply the expiry to multiple keys.

    To avoid an N+1 operation you'll need to queue multiple SET commands in a Redis Transaction or pipeline, setting each entry individually with an expiry, e.g:

    using (var trans = Redis.CreateTransaction())
    {
        foreach (var entry in dict) 
        {
            trans.QueueCommand(r => r.SetValue(entry.Key, entry.Value, expireIn));
        }
    
        trans.Commit();
    }
    

    Where ServiceStack.Redis will still send the multiple SET operations in a bulk Redis transaction.