private bool ExecutePreconditions(RedisConnectionBase conn, ref int currentDb) { if (conditions == null || conditions.Count == 0) { return(true); } Task lastTask = null; foreach (Condition cond in conditions) { lastTask = cond.Task; foreach (RedisMessage msg in cond.CreateMessages()) { conn.WriteMessage(ref currentDb, msg, null); } } conn.Flush(true); // make sure we send it all // now need to check all the preconditions passed if (lastTask != null) { conn.Wait(lastTask); } foreach (Condition cond in conditions) { if (!cond.Validate()) { return(false); } } return(true); }
private bool ExecutePreconditions(RedisConnectionBase conn, ref int currentDb) { if (conditions == null || conditions.Count == 0) { return(true); } Task lastTask = null; foreach (var cond in conditions) { lastTask = cond.Task; foreach (var msg in cond.CreateMessages()) { msg.ForceSync(); conn.WriteMessage(ref currentDb, msg, null); } } conn.Flush(true); // make sure we send it all // now need to check all the preconditions passed if (lastTask != null) { // didn't get result fast enough; treat as abort if (!lastTask.Wait(conn.SyncTimeout)) { return(false); } } foreach (var cond in conditions) { if (!cond.Validate()) { return(false); } } return(true); }
private bool ExecutePreconditions(RedisConnectionBase conn, ref int currentDb) { if (conditions == null || conditions.Count == 0) return true; Task lastTask = null; foreach (var cond in conditions) { lastTask = cond.Task; foreach (var msg in cond.CreateMessages()) { msg.ForceSync(); conn.WriteMessage(ref currentDb, msg, null); } } conn.Flush(true); // make sure we send it all // now need to check all the preconditions passed if (lastTask != null) { // didn't get result fast enough; treat as abort if (!lastTask.Wait(conn.SyncTimeout)) return false; } foreach (var cond in conditions) { if (!cond.Validate()) return false; } return true; }
void IMultiMessage.Execute(RedisConnectionBase connection, ref int currentDb) { // note: composite command in a tight time-frame! most user-facing code won't look this bad; this is just ugly // because it is infrastructure code; tough! var existsResult = new MessageResultBoolean(); var existsMessage = RedisMessage.Create(Db, RedisLiteral.EXISTS, key); // watch the key; we want changes to cause abort existsMessage.SetMessageResult(existsResult); connection.WriteMessage(ref currentDb, existsMessage, null); connection.Flush(true); // make sure it goes to the server! if we wait for it, and it is stuck // in the buffer, we've deadlocked ourself // now, we need to issue the rest of the composite command immediately to avoid multiplex issues, // so we must wait on the EXISTS, and act accordingly bool exists = connection.Wait(existsResult.Task); if (exists) { // obviously locked; just unwatch and return false connection.WriteMessage(ref currentDb, RedisMessage.Create(Db, RedisLiteral.UNWATCH), null); base.Complete(RedisResult.Integer(0)); } else { // isn't obviously locked; try a multi/setnx/expire/exec; if someone else has touched the key, this will fail and // we'll return false; otherwise, we get a lock with an expiry set connection.WriteMessage(ref currentDb, RedisMessage.Create(-1, RedisLiteral.MULTI), null); var pending = new List<QueuedMessage>(); connection.WriteMessage(ref currentDb, RedisMessage.Create(Db, RedisLiteral.SETNX, key, value), pending); connection.WriteMessage(ref currentDb, RedisMessage.Create(Db, RedisLiteral.EXPIRE, key, timeout), pending); var execResult = new MessageLockResult(); var exec = RedisMessage.Create(-1, RedisLiteral.EXEC).Critical(); exec.SetMessageResult(execResult); execResult.Task.ContinueWith(task => { if (task.Status == TaskStatus.RanToCompletion) { base.Complete(RedisResult.Integer(task.Result ? 1 : 0)); } else { base.Complete(RedisResult.Error(GetErrorMessage(task.Exception))); } }); connection.WriteMessage(ref currentDb, exec, null); } }
private bool ExecutePreconditions(RedisConnectionBase conn, ref int currentDb) { if (conditions == null || conditions.Count == 0) return true; Task lastTask = null; foreach (Condition cond in conditions) { lastTask = cond.Task; foreach (RedisMessage msg in cond.CreateMessages()) { conn.WriteMessage(ref currentDb, msg, null); } } conn.Flush(true); // make sure we send it all // now need to check all the preconditions passed if (lastTask != null) conn.Wait(lastTask); foreach (Condition cond in conditions) { if (!cond.Validate()) return false; } return true; }