private Task <long> ExecMultiAddRemove(int db, RedisLiteral command, string key, byte[][] values, bool queueJump) { RedisFeatures features; if (values.Length > 1 && ((features = Features) == null || !features.SetVaradicAddRemove)) { RedisTransaction tran = this as RedisTransaction; bool execute = false; if (tran == null) { tran = CreateTransaction(); execute = true; } Task <bool>[] tasks = new Task <bool> [values.Length]; for (int i = 0; i < values.Length; i++) { tasks[i] = ExecuteBoolean(RedisMessage.Create(db, command, key, values[i]), queueJump); } TaskCompletionSource <long> final = new TaskCompletionSource <long>(); tasks[values.Length - 1].ContinueWith(t => { try { if (t.ShouldSetResult(final)) { long count = 0; for (int i = 0; i < tasks.Length; i++) { if (tran.Wait(tasks[i])) { count++; } } final.TrySetResult(count); } } catch (Exception ex) { final.SafeSetException(ex); } }); if (execute) { tran.Execute(queueJump); } return(final.Task); } else { var args = new RedisMessage.RedisParameter[values.Length + 1]; args[0] = key; for (int i = 0; i < values.Length; i++) { args[i + 1] = values[i]; } return(ExecuteInt64(RedisMessage.Create(db, command, args), queueJump)); } }
Task <long> IHashCommands.Remove(int db, string key, string[] fields, bool queueJump) { RedisFeatures features; if (fields.Length > 1 && ((features = Features) == null || !features.HashVaradicDelete)) { RedisTransaction tran = this as RedisTransaction; bool execute = false; if (tran == null) { tran = CreateTransaction(); execute = true; } Task <bool>[] tasks = new Task <bool> [fields.Length]; var hashes = tran.Hashes; for (int i = 0; i < fields.Length; i++) { tasks[i] = hashes.Remove(db, key, fields[i], queueJump); } TaskCompletionSource <long> final = new TaskCompletionSource <long>(); tasks[fields.Length - 1].ContinueWith(t => { try { if (t.ShouldSetResult(final)) { long count = 0; for (int i = 0; i < tasks.Length; i++) { if (tran.Wait(tasks[i])) { count++; } } final.TrySetResult(count); } } catch (Exception ex) { final.SafeSetException(ex); } }); if (execute) { tran.Execute(queueJump); } return(final.Task); } else { return(ExecuteInt64(RedisMessage.Create(db, RedisLiteral.HDEL, key, fields), queueJump)); } }
// minimise delegate creations via a single static delegate instance Task <bool> IStringCommands.TakeLock(int db, string key, string value, int expirySeconds, bool queueJump) { var result = new TaskCompletionSource <bool>(); using (RedisTransaction tran = CreateTransaction()) { tran.AddCondition(Condition.KeyNotExists(db, key)); tran.Strings.Set(db, key, value, expirySeconds); tran.Execute(queueJump, state: result).ContinueWith(takeLockContinuation); } return(result.Task); }
private void OnTransactionCompleting(RedisTransaction transaction, Task<bool> transactionTask, IList<Message> messages, TaskCompletionSource<object> tcs) { if (transactionTask.IsCompleted) { try { OnTransactionComplete(transaction, transactionTask.Result, messages, tcs); } catch (OperationCanceledException) { tcs.TrySetCanceled(); } catch (Exception ex) { tcs.TrySetException(ex); } } else { transactionTask.Then(result => OnTransactionComplete(transaction, result, messages, tcs)) .ContinueWithNotComplete(tcs); } }
private void OnTransactionComplete(RedisTransaction transaction, bool success, IList<Message> messages, TaskCompletionSource<object> tcs) { if (success) { _trace.TraceVerbose("Transaction completed successfully"); tcs.TrySetResult(null); } else { _trace.TraceVerbose("Transaction failed. Retrying..."); _trace.TraceVerbose("Transaction disposed"); // Dispose the transaction transaction.Dispose(); SendImpl(messages, tcs); } }
private Task<bool> ExecuteTransaction(RedisTransaction transaction, long? oldId, IList<Message> messages) { _trace.TraceVerbose("ExecuteTransaction({0})", oldId); // New target id long newId = (oldId ?? 0) + 1; // TODO: Don't do this everytime byte[] data = RedisMessage.ToBytes(newId, messages); // These don't need to be observed transaction.AddCondition(Condition.KeyEquals(_db, _key, oldId)); transaction.Strings.Increment(_db, _key); transaction.Publish(_key, data); // Execute the transaction return transaction.Execute(); }