1

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.

Justin Homes
  • 3,739
  • 9
  • 49
  • 78

2 Answers2

1

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...

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • i have added how i have implement the redis connection – Justin Homes Sep 22 '13 at 23:47
  • @JustinHomes the edit still doesn't show me when it is killed - it just moves the question. Now, for example, the question is "ok, and when is `RedisRepository` disposed?" - because the exact same "this should be bad" and "this should be fine" examples still apply equally if we replace `OpenConnection()` with `new RedisRepository()` – Marc Gravell Sep 23 '13 at 06:59
  • i added a sleep of 5 seconds before i exit my console app and it did the trick. i guess the console app was exiting before the threads were done?? – Justin Homes Sep 25 '13 at 05:35
  • @JustinHomes again, I can't directly comment on that without seeing the structure of the console exe. The best way is to add the `using` or to `Wait` on the last result - as shown in the examples. Waiting a random amount of time is not, IMO, the best approach. – Marc Gravell Sep 25 '13 at 06:49
  • i do have wait for the task threads that creates instances of redis connections , but how do i add a wait for a bookshelves library thread that does async call to redis? – Justin Homes Sep 25 '13 at 20:25
  • @Justin - well, commands are sent in order. You could just issue a ping and wait on that... – Marc Gravell Sep 25 '13 at 20:26
0

Maybe you have to wait until the asynchronous removes are completed.

Try this code:

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

   _redisClient.WaitAll(removeTasks);
}
Alberto
  • 15,626
  • 9
  • 43
  • 56