1

I'm trying to set multiple fields of a hash independently and retrieve them all at once later on. Is the code below supposed to work or am doing something wrong here? When I run it locally against redis-2.0.0-x64 on Windows downloaded from the Service Stack site, the result of task3 will always just contains field2.

var con = RedisConnectionManager.Instance.GetConnection();
var key = "somekey1";

// set the field value and expiration
var task = con.Hashes.Set(1, key, "field1", token.ToByteArray())
    .ContinueWith((x)=> con.Keys.Expire(1, key, 7200));
task.Wait();

var task2 = con.Hashes.Set(1, key, "field2", "fooobar");
task2.Wait();

var task3 = con.Hashes.GetAll(1, key);
task3.Wait();
Oliver Weichhold
  • 10,259
  • 5
  • 45
  • 87

1 Answers1

1

Cannot reproduce this on a reasonably current version of redis - looks fine here:

using (var con = Config.GetUnsecuredConnection())
{
    var key = "somekey1";

    // set the field value and expiration
    var task = con.Hashes.Set(1, key, "field1", Encoding.UTF8.GetBytes("hello world"))
        .ContinueWith((x) => con.Keys.Expire(1, key, 7200));
    task.Wait();

    var task2 = con.Hashes.Set(1, key, "field2", "fooobar");
    task2.Wait();

    var task3 = con.Hashes.GetAll(1, key);
    task3.Wait();

    Assert.AreEqual(2, task3.Result.Count);
    Assert.AreEqual("hello world", Encoding.UTF8.GetString(task3.Result["field1"]));
    Assert.AreEqual("fooobar", Encoding.UTF8.GetString(task3.Result["field2"]));
}

or, more efficiently (uses pipelining, by not waiting):

using (var con = Config.GetUnsecuredConnection())
{
    var key = "somekey1";

    // set the field value and expiration
    con.Hashes.Set(1, key, "field1", Encoding.UTF8.GetBytes("hello world"));
    con.Keys.Expire(1, key, 7200);
    con.Hashes.Set(1, key, "field2", "fooobar");
    var task = con.Hashes.GetAll(1, key);
    con.Wait(task);

    Assert.AreEqual(2, task.Result.Count);
    Assert.AreEqual("hello world", Encoding.UTF8.GetString(task.Result["field1"]));
    Assert.AreEqual("fooobar", Encoding.UTF8.GetString(task.Result["field2"]));
}

So yes: should work, and seems to work. Note I'm using 2.4.5 locally; 2.0 is very old now, and has a number of important bugs. It is entirely possible that there was a bug relating to HSET plus EXPIRE at the server - in which case there isn't much the client library can do to compensate.

I strongly suggest using a more "current" build of redis-server than 2.0. If one isn't available, you might want to try the dmajkic binaries (goes to 2.4.5), or the [MSOpenTech]*https://github.com/MSOpenTech/redis) source. However!!! This is just for local debugging. For production work at the current time (i.e. until the MSOpenTech code is happy-happy), I would recommend using a linux server to host redis. Ubuntu Server works well.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Switching to dmajkic's binaries immediately made the problem go away. In regard to your remarks about pipelining: This was just a compilation of the actions my code is taking. In reality the two Set actions happen in two different locations of the code and in reality there also isn't a task.Wait() after the Set() call which I suppose is ok since the connection is shared globally so dirty reads shouldn't happen. Right? – Oliver Weichhold May 31 '12 at 06:22
  • 1
    @Oliver the pipe is ordered - if you issue the Set before the GetAll (regardless of which thread etc), then the pipe will preserve that order – Marc Gravell May 31 '12 at 06:31
  • One question if you don't mind (even it is more Redis related than Booksleeve related). If I set an expiry, will it stil be persisted? (would like to prevent a cachestorm) – Oliver Weichhold May 31 '12 at 07:06
  • @Oliver do you mean to disk? Well, that depends on your persistence configuration, most specifically: **when** the data gets saved. If the key is still valid (i.e. hasn't expired) when the server gets saved to disk, then yes: the key will be included. Once the key expires: not so much. – Marc Gravell May 31 '12 at 07:09
  • Thats exactly the behavior I was hoping to get. Thanks again. – Oliver Weichhold May 31 '12 at 07:50