/// <summary> /// INCRBYFLOAT http://redis.io/commands/incrbyfloat /// </summary> public Task <double> Decrement(double value = 1, RedisExpiry expiry = null, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { var r = await this.ExecuteWithKeyExpire(x => x.StringDecrementAsync(Key, value, commandFlags), Key, expiry, commandFlags).ForAwait(); return Tracing.CreateSentAndReceived(new { value, expiry = expiry?.Value }, sizeof(double), r, sizeof(double)); })); }
/// <summary> /// SETBIT http://redis.io/commands/setbit /// </summary> public Task <bool> SetBit(long offset, bool bit, RedisExpiry expiry = null, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { var r = await this.ExecuteWithKeyExpire(x => x.StringSetBitAsync(Key, offset, bit, commandFlags), Key, expiry, commandFlags).ForAwait(); return Tracing.CreateSentAndReceived(new { offset, bit, expiry = expiry?.Value }, sizeof(long) * 2, r, sizeof(bool)); })); }
/// <summary> /// RPUSH http://redis.io/commands/rpush /// </summary> public Task <long> RightPush(T value, RedisExpiry expiry = null, When when = When.Always, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { long sentSize; var v = Settings.ValueConverter.Serialize(value, out sentSize); var vr = await this.ExecuteWithKeyExpire(x => x.ListRightPushAsync(Key, v, when, commandFlags), Key, expiry, commandFlags).ForAwait(); return Tracing.CreateSentAndReceived(new { value, expiry = expiry?.Value, when }, sentSize, vr, sizeof(long)); })); }
/// <summary> /// SADD http://redis.io/commands/sadd /// </summary> public Task <bool> Add(T value, RedisExpiry expiry = null, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { long sentSize; var v = Settings.ValueConverter.Serialize(value, out sentSize); var r = await this.ExecuteWithKeyExpire(x => x.SetAddAsync(Key, v, commandFlags), Key, expiry, commandFlags).ForAwait(); return Tracing.CreateSentAndReceived(new { value, expiry = expiry?.Value }, sentSize, r, sizeof(bool)); })); }
/// <summary> /// LSET http://redis.io/commands/lset /// </summary> public Task SetByIndex(int index, T value, RedisExpiry expiry = null, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSend(Settings, Key, CallType, async() => { long sentSize; var v = Settings.ValueConverter.Serialize(value, out sentSize); await this.ExecuteWithKeyExpire(x => x.ListSetByIndexAsync(Key, index, v, commandFlags), Key, expiry, commandFlags).ForAwait(); return Tracing.CreateSent(new { index, value }, sentSize); })); }
/// <summary> /// ZINCRBY http://redis.io/commands/zincrby /// </summary> public Task <double> Decrement(T member, double value, RedisExpiry expiry = null, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { long size; var v = Settings.ValueConverter.Serialize(member, out size); var r = await this.ExecuteWithKeyExpire(x => x.SortedSetDecrementAsync(Key, v, value, commandFlags), Key, expiry, commandFlags).ForAwait(); return Tracing.CreateSentAndReceived(new { member, value, expiry = expiry?.Value }, size, r, sizeof(double)); })); }
/// <summary> /// HINCRBYFLOAT http://redis.io/commands/hincrbyfloat /// </summary> public Task <double> Increment(TKey field, double value, RedisExpiry expiry = null, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { long keySize; var rKey = Settings.ValueConverter.Serialize(field, out keySize); var r = await this.ExecuteWithKeyExpire(x => x.HashIncrementAsync(Key, rKey, value, commandFlags), Key, expiry, commandFlags).ForAwait(); return Tracing.CreateSentAndReceived(new { field, value }, keySize, r, sizeof(long)); })); }
/// <summary> /// LUA Script including hincrby, hset /// </summary> public Task <long> IncrementLimitByMin(TKey field, long value, long max, RedisExpiry expiry = null, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { long keySize; var rKey = (RedisKey)(byte[])Settings.ValueConverter.Serialize(field, out keySize); var v = await this.ExecuteWithKeyExpire(x => x.ScriptEvaluateAsync(HashScript.IncrementLimitByMin, new[] { Key, rKey }, new RedisValue[] { value, max }, commandFlags), Key, expiry, commandFlags).ForAwait(); var r = (long)v; return Tracing.CreateSentAndReceived(new { field, value, max, expiry = expiry?.Value }, keySize + sizeof(long) * 2, r, sizeof(long)); })); }
/// <summary> /// LINSERT http://redis.io/commands/linsert /// </summary> public Task <long> InsertBefore(T pivot, T value, RedisExpiry expiry = null, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { long sentSize1; long sentSize2; var p = Settings.ValueConverter.Serialize(pivot, out sentSize1); var v = Settings.ValueConverter.Serialize(value, out sentSize2); var vr = await this.ExecuteWithKeyExpire(x => x.ListInsertBeforeAsync(Key, p, v, commandFlags), Key, expiry, commandFlags).ForAwait(); return Tracing.CreateSentAndReceived(new { pivot, value, expiry = expiry?.Value }, sentSize1 + sentSize2, vr, sizeof(long)); })); }
/// <summary> /// GETSET http://redis.io/commands/getset /// </summary> public Task <T> GetSet(T value, RedisExpiry expiry = null, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { long sentSize; long receivedSize; var v = Settings.ValueConverter.Serialize(value, out sentSize); var result = await this.ExecuteWithKeyExpire(x => x.StringGetSetAsync(Key, v, commandFlags), Key, expiry, commandFlags).ForAwait(); var r = Settings.ValueConverter.Deserialize <T>(result, out receivedSize); return Tracing.CreateSentAndReceived(new { value, expiry = expiry?.Value }, sentSize, r, receivedSize); })); }
/// <summary> /// GET, SET http://redis.io/commands/get http://redis.io/commands/set /// </summary> public async Task <T> GetOrSet(Func <Task <T> > valueFactory, RedisExpiry expiry = null, bool keepValueFactorySynchronizationContext = false, CommandFlags commandFlags = CommandFlags.None) { var value = await Get(commandFlags).ConfigureAwait(keepValueFactorySynchronizationContext); // can choose valueFactory synchronization context if (value.HasValue) { return(value.Value); } else { var v = await valueFactory().ForAwait(); await Set(v, expiry, When.Always, commandFlags).ForAwait(); return(v); } }
/// <summary> /// SADD http://redis.io/commands/sadd /// </summary> public Task <long> Add(T[] values, RedisExpiry expiry = null, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { var sentSize = 0L; var redisValues = values.Select(x => { long _size; var rv = Settings.ValueConverter.Serialize(x, out _size); sentSize += _size; return rv; }).ToArray(); var vr = await this.ExecuteWithKeyExpire(x => x.SetAddAsync(Key, redisValues, commandFlags), Key, expiry, commandFlags).ForAwait(); return Tracing.CreateSentAndReceived(new { values, expiry = expiry?.Value }, sentSize, vr, sizeof(long)); })); }
/// <summary> /// LUA Script including incrbyfloat, set /// </summary> public Task <double> IncrementLimitByMin(double value, double min, RedisExpiry expiry = null, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { var v = await this.ExecuteWithKeyExpire(x => x.ScriptEvaluateAsync(@" local inc = tonumber(ARGV[1]) local min = tonumber(ARGV[2]) local x = tonumber(redis.call('incrbyfloat', KEYS[1], inc)) if(x < min) then redis.call('set', KEYS[1], min) x = min end return tostring(x)", new[] { Key }, new RedisValue[] { value, min }, commandFlags), Key, expiry, commandFlags).ForAwait(); var r = double.Parse((string)v); return Tracing.CreateSentAndReceived(new { value, min, expiry = expiry?.Value }, sizeof(double) * 2, r, sizeof(double)); })); }
/// <summary> /// LUA Script including incrby, set /// </summary> public Task <long> IncrementLimitByMax(long value, long max, RedisExpiry expiry = null, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { var v = await this.ExecuteWithKeyExpire(x => x.ScriptEvaluateAsync(@" local inc = tonumber(ARGV[1]) local max = tonumber(ARGV[2]) local x = redis.call('incrby', KEYS[1], inc) if(x > max) then redis.call('set', KEYS[1], max) x = max end return x", new[] { Key }, new RedisValue[] { value, max }, commandFlags), Key, expiry, commandFlags).ForAwait(); var r = (long)v; return Tracing.CreateSentAndReceived(new { value, max, expiry = expiry?.Value }, sizeof(long) * 2, r, sizeof(long)); })); }
// additional commands /// <summary> /// Simulate fixed size list includes LPUSH, TRIM. /// </summary> public Task <long> LeftPushAndFixLength(T value, long fixLength, RedisExpiry expiry = null, When when = When.Always, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { long sentSize; var v = Settings.ValueConverter.Serialize(value, out sentSize); var tx = CreateTransaction(); var leftpush = tx.ListLeftPushAsync(Key, v, when, commandFlags); var trim = tx.ListTrimAsync(Key, 0, fixLength - 1, commandFlags); if (expiry != null) { var expire = expiry.KeyExpire(tx, Key, commandFlags); } await tx.ExecuteAsync(commandFlags).ForAwait(); var r = await leftpush.ForAwait(); return Tracing.CreateSentAndReceived(new { value, fixLength, expiry = expiry?.Value, when }, sentSize, r, sizeof(long)); })); }
/// <summary> /// SET http://redis.io/commands/set /// </summary> public Task <bool> Set(T value, RedisExpiry expiry = null, When when = When.Always, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { long sentSize; var v = Settings.ValueConverter.Serialize(value, out sentSize); bool r; if (expiry != null && expiry.IsTimeSpan) { r = await Command.StringSetAsync(Key, v, (TimeSpan)expiry.Value, when, CommandFlags.None).ForAwait(); } else { r = await this.ExecuteWithKeyExpire(x => x.StringSetAsync(Key, v, expiry: null, when: when, flags: commandFlags), Key, expiry, commandFlags).ForAwait(); } return Tracing.CreateSentAndReceived(new { value, expiry, when }, sentSize, r, sizeof(bool)); })); }
/// <summary> /// LUA Script including zincrby, zadd /// </summary> public Task <double> IncrementLimitByMax(T member, double value, double max, RedisExpiry expiry = null, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { long size; var mv = Settings.ValueConverter.Serialize(member, out size); var v = await this.ExecuteWithKeyExpire(x => x.ScriptEvaluateAsync(@" local mem = ARGV[1] local inc = tonumber(ARGV[2]) local max = tonumber(ARGV[3]) local x = tonumber(redis.call('zincrby', KEYS[1], inc, mem)) if(x > max) then redis.call('zadd', KEYS[1], max, mem) x = max end return tostring(x)", new[] { Key }, new RedisValue[] { mv, value, max }, commandFlags), Key, expiry, commandFlags).ForAwait(); var r = double.Parse((string)v); return Tracing.CreateSentAndReceived(new { value, max, expiry = expiry?.Value }, size, r, sizeof(double)); })); }
/// <summary> /// ZADD http://redis.io/commands/zadd /// </summary> public Task <long> Add(IEnumerable <KeyValuePair <T, double> > values, RedisExpiry expiry = null, CommandFlags commandFlags = CommandFlags.None) { return(TraceHelper.RecordSendAndReceive(Settings, Key, CallType, async() => { // materialize if (!(values is ICollection)) { values = values.ToArray(); } long sentSize = 0; var sendValues = values.Select(x => { long s; var v = Settings.ValueConverter.Serialize(x.Key, out s); sentSize += s; return new SortedSetEntry(v, x.Value); }).ToArray(); var vr = await this.ExecuteWithKeyExpire(x => x.SortedSetAddAsync(Key, sendValues, commandFlags), Key, expiry, commandFlags).ForAwait(); return Tracing.CreateSentAndReceived(new { values, expiry = expiry?.Value }, sentSize, vr, sizeof(long)); })); }
public static async Task <T> ExecuteWithKeyExpire <T>(this RedisStructure redisStructure, Func <IDatabaseAsync, Task <T> > command, RedisKey key, RedisExpiry expiry, CommandFlags commandFlags) { if (expiry == null) { return(await command(redisStructure.Command).ForAwait()); } else { var tx = redisStructure.CreateTransaction(); var future = command(tx); var expire = expiry.KeyExpire(tx, key, commandFlags); await tx.ExecuteAsync(commandFlags).ForAwait(); return(await future.ForAwait()); } }