public RedisLock(RedisClient redisClient, string key, TimeSpan? timeOut) { this.redisClient = redisClient; this.key = key; ExecExtensions.RetryUntilTrue( () => { //This pattern is taken from the redis command for SETNX http://redis.io/commands/setnx //Calculate a unix time for when the lock should expire TimeSpan realSpan = timeOut ?? new TimeSpan(365, 0, 0, 0); //if nothing is passed in the timeout hold for a year DateTime expireTime = DateTime.UtcNow.Add(realSpan); string lockString = (expireTime.ToUnixTimeMs() + 1).ToString(); //Try to set the lock, if it does not exist this will succeed and the lock is obtained var nx = redisClient.SetValueIfNotExists(key, lockString); if (nx) return true; //If we've gotten here then a key for the lock is present. This could be because the lock is //correctly acquired or it could be because a client that had acquired the lock crashed (or didn't release it properly). //Therefore we need to get the value of the lock to see when it should expire redisClient.Watch(key); string lockExpireString = redisClient.Get<string>(key); long lockExpireTime; if (!long.TryParse(lockExpireString, out lockExpireTime)) { redisClient.UnWatch(); // since the client is scoped externally return false; } //If the expire time is greater than the current time then we can't let the lock go yet if (lockExpireTime > DateTime.UtcNow.ToUnixTimeMs()) { redisClient.UnWatch(); // since the client is scoped externally return false; } //If the expire time is less than the current time then it wasn't released properly and we can attempt to //acquire the lock. The above call to Watch(_lockKey) enrolled the key in monitoring, so if it changes //before we call Commit() below, the Commit will fail and return false, which means that another thread //was able to acquire the lock before we finished processing. using (var trans = redisClient.CreateTransaction()) // we started the "Watch" above; this tx will succeed if the value has not moved { trans.QueueCommand(r => r.Set(key, lockString)); return trans.Commit(); //returns false if Transaction failed } }, timeOut ); }
public RedisLock(RedisClient redisClient, string key, TimeSpan?timeOut) { this.redisClient = redisClient; this.key = key; ExecExtensions.RetryUntilTrue( () => { //This pattern is taken from the redis command for SETNX http://redis.io/commands/setnx //Calculate a unix time for when the lock should expire TimeSpan realSpan = timeOut ?? new TimeSpan(365, 0, 0, 0); //if nothing is passed in the timeout hold for a year DateTime expireTime = DateTime.UtcNow.Add(realSpan); string lockString = (expireTime.ToUnixTimeMs() + 1).ToString(); //Try to set the lock, if it does not exist this will succeed and the lock is obtained var nx = redisClient.SetValueIfNotExists(key, lockString); if (nx) { return(true); } //If we've gotten here then a key for the lock is present. This could be because the lock is //correctly acquired or it could be because a client that had acquired the lock crashed (or didn't release it properly). //Therefore we need to get the value of the lock to see when it should expire redisClient.Watch(key); string lockExpireString = redisClient.Get <string>(key); long lockExpireTime; if (!long.TryParse(lockExpireString, out lockExpireTime)) { redisClient.UnWatch(); // since the client is scoped externally return(false); } //If the expire time is greater than the current time then we can't let the lock go yet if (lockExpireTime > DateTime.UtcNow.ToUnixTimeMs()) { redisClient.UnWatch(); // since the client is scoped externally return(false); } //If the expire time is less than the current time then it wasn't released properly and we can attempt to //acquire the lock. The above call to Watch(_lockKey) enrolled the key in monitoring, so if it changes //before we call Commit() below, the Commit will fail and return false, which means that another thread //was able to acquire the lock before we finished processing. using (var trans = redisClient.CreateTransaction()) // we started the "Watch" above; this tx will succeed if the value has not moved { trans.QueueCommand(r => r.Set(key, lockString)); return(trans.Commit()); //returns false if Transaction failed } }, timeOut ); }
static void Main(string[] args) { /*** String ***/ using (IRedisNativeClient client = new RedisClient()) { client.Set("urn:messages:1", Encoding.UTF8.GetBytes("Hello C# World!")); } using (IRedisNativeClient client = new RedisClient()) { var result = Encoding.UTF8.GetString(client.Get("urn:messages:1")); Console.WriteLine("Message: {0}", result); } /*** Lists ***/ using (IRedisClient client = new RedisClient()) { var customerNames = client.Lists["urn:customernames"]; customerNames.Clear(); customerNames.Add("Joe"); customerNames.Add("Mary"); customerNames.Add("Bob"); } using (IRedisClient client = new RedisClient()) { var customerNames = client.Lists["urn:customernames"]; foreach (var customerName in customerNames) { Console.WriteLine("Customer {0}", customerName); } } /*** Object ***/ long lastId = 0; using (IRedisClient client = new RedisClient()) { var customerClient = client.GetTypedClient<Customer>(); var customer = new Customer() { Id = customerClient.GetNextSequence(), Address = "123 Main St", Name = "Bob Green", Orders = new List<Order> { new Order { OrderNumber = "AB123"}, new Order { OrderNumber = "AB124"} } }; var storedCustomer = customerClient.Store(customer); lastId = storedCustomer.Id; } using (IRedisClient client = new RedisClient()) { var customerClient = client.GetTypedClient<Customer>(); var customer = customerClient.GetById(lastId); Console.WriteLine("Got customer {0}, with name {1}", customer.Id, customer.Name); } /*** Transaction ***/ using (IRedisClient client = new RedisClient()) { var transaction = client.CreateTransaction(); transaction.QueueCommand(c => c.Set("abc", 1)); transaction.QueueCommand(c => c.Increment("abc", 1)); transaction.Commit(); var result = client.Get<int>("abc"); Console.WriteLine(result); } /*** Publishing & Subscribing ***/ using (IRedisClient client = new RedisClient()) { client.PublishMessage("debug", "Hello C#!"); var sub = client.CreateSubscription(); sub.OnMessage = (c, m) => Console.WriteLine("Got message {0}, from channel {1}", m, c); sub.SubscribeToChannels("news"); } Console.ReadLine(); }