private bool SetNoScript(CacheItem <TCacheValue> item, StackRedis.When when, bool sync = false) { return(this.Retry(() => { var fullKey = GetKey(item.Key, item.Region); var value = this.ToRedisValue(item.Value); StackRedis.HashEntry[] metaValues = new[] { new StackRedis.HashEntry(HashFieldType, item.ValueType.AssemblyQualifiedName), new StackRedis.HashEntry(HashFieldExpirationMode, (int)item.ExpirationMode), new StackRedis.HashEntry(HashFieldExpirationTimeout, (long)item.ExpirationTimeout.TotalMilliseconds), new StackRedis.HashEntry(HashFieldCreated, item.CreatedUtc.Ticks), new StackRedis.HashEntry(HashFieldUsesDefaultExp, item.UsesExpirationDefaults) }; var flags = sync ? StackRedis.CommandFlags.None : StackRedis.CommandFlags.FireAndForget; var setResult = this.connection.Database.HashSet(fullKey, HashFieldValue, value, when, flags); // setResult from fire and forget is alwys false, so we have to assume it works... setResult = flags == StackRedis.CommandFlags.FireAndForget ? true : setResult; if (setResult) { if (!string.IsNullOrWhiteSpace(item.Region)) { // setting region lookup key if region is being used this.connection.Database.HashSet(item.Region, fullKey, "regionKey", StackRedis.When.Always, StackRedis.CommandFlags.FireAndForget); } // set the additional fields in case sliding expiration should be used in this // case we have to store the expiration mode and timeout on the hash, too so // that we can extend the expiration period every time we do a get if (metaValues != null) { this.connection.Database.HashSet(fullKey, metaValues, flags); } if (item.ExpirationMode != ExpirationMode.None && item.ExpirationMode != ExpirationMode.Default) { this.connection.Database.KeyExpire(fullKey, item.ExpirationTimeout, StackRedis.CommandFlags.FireAndForget); } else { // bugfix #9 this.connection.Database.KeyPersist(fullKey, StackRedis.CommandFlags.FireAndForget); } } return setResult; })); }
#pragma warning disable CSE0003 private bool Set(CacheItem <TCacheValue> item, StackRedis.When when, bool sync = false) { // TODO: move the whole logic into a script to make it atomic return(this.Retry(() => { var fullKey = GetKey(item.Key, item.Region); var value = this.ToRedisValue(item.Value); StackRedis.HashEntry[] metaValues = new[] { new StackRedis.HashEntry(HashFieldType, item.ValueType.AssemblyQualifiedName), new StackRedis.HashEntry(HashFieldExpirationMode, (int)item.ExpirationMode), new StackRedis.HashEntry(HashFieldExpirationTimeout, item.ExpirationTimeout.Ticks), new StackRedis.HashEntry(HashFieldCreated, item.CreatedUtc.Ticks) }; var flags = sync ? StackRedis.CommandFlags.None : StackRedis.CommandFlags.FireAndForget; var setResult = this.Database.HashSet(fullKey, HashFieldValue, value, when, flags); // setResult from fire and forget is alwys false, so we have to assume it works... setResult = flags == StackRedis.CommandFlags.FireAndForget ? true : setResult; if (setResult) { // update region lookup if (!string.IsNullOrWhiteSpace(item.Region)) { this.Database.HashSet(item.Region, item.Key, "regionKey", when, StackRedis.CommandFlags.FireAndForget); } // set the additional fields in case sliding expiration should be used in this // case we have to store the expiration mode and timeout on the hash, too so // that we can extend the expiration period every time we do a get if (metaValues != null) { this.Database.HashSet(fullKey, metaValues, flags); } if (item.ExpirationMode != ExpirationMode.None) { this.Database.KeyExpire(fullKey, item.ExpirationTimeout, StackRedis.CommandFlags.FireAndForget); } else { // bugfix #9 this.Database.KeyExpire(fullKey, default(TimeSpan?), StackRedis.CommandFlags.FireAndForget); } } return setResult; })); }
private bool Set(CacheItem <TCacheValue> item, StackRedis.When when, bool sync = false) { if (!this.isLuaAllowed) { return(this.SetNoScript(item, when, sync)); } var fullKey = GetKey(item.Key, item.Region); var value = this.ToRedisValue(item.Value); var flags = sync ? StackRedis.CommandFlags.None : StackRedis.CommandFlags.FireAndForget; // ARGV [1]: value, [2]: type, [3]: expirationMode, [4]: expirationTimeout(millis), [5]: created(ticks) var parameters = new StackRedis.RedisValue[] { value, item.ValueType.AssemblyQualifiedName, (int)item.ExpirationMode, item.ExpirationTimeout.TotalMilliseconds, item.CreatedUtc.Ticks }; StackRedis.RedisResult result; if (when == StackRedis.When.NotExists) { result = this.Eval(ScriptType.Add, fullKey, parameters, flags); } else { result = this.Eval(ScriptType.Put, fullKey, parameters, flags); } if (result == null) { if (flags.HasFlag(StackRedis.CommandFlags.FireAndForget)) { // put runs via fire and forget, so we don't get a result back return(true); } // should never happen, something went wrong with the script throw new InvalidOperationException("Something went wrong adding an item, result must not be null."); } else { if (result.IsNull && when == StackRedis.When.NotExists) { // add failed because element exists already return(false); } var resultValue = (StackRedis.RedisValue)result; if (resultValue.HasValue && resultValue.ToString().Equals("OK", StringComparison.OrdinalIgnoreCase)) { // Added successfully: if (!string.IsNullOrWhiteSpace(item.Region)) { // now update region lookup if region is set // we cannot do that within the lua because the region could be on another cluster node! this.connection.Database.HashSet(item.Region, fullKey, "regionKey", when, StackRedis.CommandFlags.FireAndForget); } return(true); } return(false); } }