Search code examples
booksleeve

Booksleeve - Setting multiple Hash Values and retrieve them at once


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();

Solution

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