Search code examples
c#c#-4.0redisbooksleeve

Remove SortedSet using BookSleeve


I have around 336 keys that i am trying to remove which are SortedSets, i am using BookSleeve as C3 Client with Redis on Ubuntuserver. the code below works, but if i remove the Console.WriteLine it randomly does not delete around 100 keys. it does not throw any error, when i turn on Montior on redis server side i do not see a ZREM statment being sent for those not delete ones from c# side. why would it work with Console.Writeline present and not when it is commented out baffles me. any ideas?

public virtual void RemoveKey(string item, string id)
{
   for (int i = 1; i <= item.Length; i++)
   {
      Console.WriteLine(PrefixKey + item.Substring(0, i));
      _redisClient.SortedSets.Remove(_database, 
             PrefixKey + item.Substring(0, i), id);
   }
}

I have a class

 public class RedisRepository
    {
        protected static RedisConnection _redisClient;
        protected int _database;
        protected bool disposed;

        public RedisRepository(int database)
        {
            string server = ConfigurationManager.AppSettings["redis.server"];
            int port = Convert.ToInt32(ConfigurationManager.AppSettings["redis.port"]);
            string password = ConfigurationManager.AppSettings["redis.password"];
            _redisClient = new RedisConnection(server, port, -1, password);
            _database = database;
            _redisClient.Open();
        }
     ~RedisRepository()
        {
            this.Dispose(false);
        }

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);

        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    _redisClient.CloseAsync(false);
                    _redisClient.Dispose();
                }

                // Dispose unmanaged resources here.
            }

            disposed = true;
        }
}

I have inherited above RedisRpository class into another class that uses its _redisClient object.


Solution

  • This is a bit hard to answer without seeing the lifetime cycle of _redisClient. In particular, all operations of RedisConnection are asynchronous. If you are running a test that starts the operations and then exists immediately : some things may still be waiting on the socket. If redis detects a socket-close, it kills that connection immediately (it doesn't even drain the socket first, so pending operations are ignored). If your process terminates, the socket will close abruptly.

    If, however, you are using "using", it should work fine - the dispose implementation should ensure it it closed properly.

    So basically this would be bad:

    static void Main() {
        var conn = OpenConnection();
        // lots of operations
    }
    

    But this should be fine:

    static void Main() {
        using(var conn = OpenConnection()) {
             // lots of operations
        }
    }
    

    Alternatively, you could track the last operation and simply wait on in:

    Task last = null;
    for(...) {
         last = conn.SomeOperation(...);
    }
    if(last != null) conn.Wait(last);
    

    If it isn't related to any of these, a full example would really help...