Esempio n. 1
0
        /// <summary>
        /// 异步的,尝试获取指定缓存键的对象,如果没有则使用函数添加对象到缓存中。
        /// </summary>
        /// <typeparam name="T">缓存对象的类型。</typeparam>
        /// <param name="cacheKey">用于引用对象的缓存键。</param>
        /// <param name="valueCreator">用于添加缓存对象的函数。</param>
        /// <param name="expiration">判断对象过期的对象。</param>
        /// <param name="cancellationToken">取消操作的通知。</param>
        /// <returns></returns>
        public async Task <T> TryGetAsync <T>(string cacheKey, Func <Task <T> > valueCreator, Func <ICacheItemExpiration> expiration = null, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            cacheKey = ServiceProvider.GetCacheKey(cacheKey);
            var client = GetConnection(cacheKey);

            try
            {
                async Task <CheckCache <T> > GetCacheValue()
                {
                    if (await client.ExistsAsync(cacheKey))
                    {
                        var redisValue = await client.GetAsync(cacheKey);

                        if (!string.IsNullOrEmpty(redisValue))
                        {
                            await HandleSlidingTimeAsync(client, cacheKey);

                            return(CheckCache <T> .Result(Deserialize <T>(redisValue)));
                        }
                    }

                    return(CheckCache <T> .Null());
                }

                var ck = await GetCacheValue();

                if (ck.HasValue)
                {
                    return(ck.Value);
                }

                return(await RedisHelper.LockAsync(client, GetLockToken(cacheKey), Setting.LockTimeout, async() =>
                {
                    var ck1 = await GetCacheValue();
                    if (ck1.HasValue)
                    {
                        return ck1.Value;
                    }

                    var expiry = GetExpirationTime(expiration);
                    var value = await valueCreator();

                    await client.SetAsync(cacheKey, Serialize(value), expiry == null ? -1 : (int)expiry.Value.TotalSeconds);

                    return value;
                }));
            }
            catch (IOException exp)
            {
                if (Setting.IgnoreException)
                {
                    Tracer.Error($"RedisCache TryGetValue throw exception:\n{exp.Output()}");
                    return(await valueCreator());
                }

                throw exp;
            }
        }
Esempio n. 2
0
        /// <summary>
        /// 尝试获取指定缓存键的对象,如果没有则使用函数添加对象到缓存中。
        /// </summary>
        /// <typeparam name="T">缓存对象的类型。</typeparam>
        /// <param name="cacheKey">用于引用对象的缓存键。</param>
        /// <param name="valueCreator">用于添加缓存对象的函数。</param>
        /// <param name="expiration">判断对象过期的对象。</param>
        /// <returns></returns>
        public T TryGet <T>(string cacheKey, Func <T> valueCreator, Func <ICacheItemExpiration> expiration = null)
        {
            cacheKey = ServiceProvider.GetCacheKey(cacheKey);
            var client = GetConnection(cacheKey);

            try
            {
                CheckCache <T> GetCacheValue()
                {
                    if (client.Exists(cacheKey))
                    {
                        var redisValue = client.Get(cacheKey);
                        if (!string.IsNullOrEmpty(redisValue))
                        {
                            HandleSlidingTime(client, cacheKey);

                            return(CheckCache <T> .Result(Deserialize <T>(redisValue)));
                        }
                    }

                    return(CheckCache <T> .Null());
                }

                var ck = GetCacheValue();
                if (ck.HasValue)
                {
                    return(ck.Value);
                }

                return(RedisHelper.Lock(client, GetLockToken(cacheKey), Setting.LockTimeout, () =>
                {
                    var ck1 = GetCacheValue();
                    if (ck1.HasValue)
                    {
                        return ck1.Value;
                    }

                    var expiry = GetExpirationTime(expiration);
                    var value = valueCreator();

                    client.Set(cacheKey, base.Serialize(value), expiry == null ? -1 : (int)expiry.Value.TotalSeconds);

                    return value;
                }));
            }
            catch (IOException exp)
            {
                if (Setting.IgnoreException)
                {
                    Tracer.Error($"RedisCache TryGetValue throw exception:\n{exp.Output()}");
                    return(valueCreator());
                }

                throw exp;
            }
        }
Esempio n. 3
0
        /// <summary>
        /// 异步的,尝试从集合中获取指定 <paramref name="key"/> 的数据,如果没有则使用函数添加对象到集合中。
        /// </summary>
        /// <param name="key">标识数据的 key。</param>
        /// <param name="valueCreator">用于添加缓存对象的函数。</param>
        /// <param name="expiration">判断对象过期的对象。</param>
        /// <param name="cancellationToken">取消操作的通知。</param>
        /// <returns></returns>
        public async Task <TValue> TryGetAsync(TKey key, Func <Task <TValue> > valueCreator, Func <ICacheItemExpiration> expiration = null, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            TryReInitialize();

            var sKey = key.ToString();

            async Task <CheckCache <TValue> > GetCacheValue()
            {
                if (await _client.HExistsAsync(_cacheKey, sKey))
                {
                    var content = await _client.HGetAsync(_cacheKey, sKey);

                    var item = _deserialize(content);
                    if (!item.HasExpired())
                    {
                        return(CheckCache <TValue> .Result(item.Value));
                    }
                }

                return(CheckCache <TValue> .Null());
            }

            var ck = await GetCacheValue();

            if (ck.HasValue)
            {
                return(ck.Value);
            }

            return(await RedisHelper.LockAsync(_client, string.Concat(_cacheKey, ":", sKey), _setting.LockTimeout, async() =>
            {
                var ck1 = await GetCacheValue();
                if (ck1.HasValue)
                {
                    return ck1.Value;
                }

                var value = await valueCreator();
                var content = _serialize(new RedisCacheItem <TValue>(value, expiration == null ? NeverExpired.Instance : expiration()));
                await _client.HSetAsync(_cacheKey, sKey, content);
                return value;
            }));
        }
Esempio n. 4
0
        /// <summary>
        /// 尝试从集合中获取指定 <paramref name="key"/> 的数据,如果没有则使用函数添加对象到集合中。
        /// </summary>
        /// <param name="key">标识数据的 key。</param>
        /// <param name="valueCreator">用于添加缓存对象的函数。</param>
        /// <param name="expiration">判断对象过期的对象。</param>
        /// <returns></returns>
        public TValue TryGet(TKey key, Func <TValue> valueCreator, Func <ICacheItemExpiration> expiration = null)
        {
            TryReInitialize();

            var sKey = key.ToString();

            CheckCache <TValue> GetCacheValue()
            {
                if (_client.HExists(_cacheKey, sKey))
                {
                    var content = _client.HGet(_cacheKey, sKey);
                    var item    = _deserialize(content);
                    if (!item.HasExpired())
                    {
                        return(CheckCache <TValue> .Result(item.Value));
                    }
                }

                return(CheckCache <TValue> .Null());
            }

            var ck = GetCacheValue();

            if (ck.HasValue)
            {
                return(ck.Value);
            }

            return(RedisHelper.Lock(_client, string.Concat(_cacheKey, ":", sKey), _setting.LockTimeout, () =>
            {
                var ck1 = GetCacheValue();
                if (ck1.HasValue)
                {
                    return ck1.Value;
                }

                var value = valueCreator();
                var content = _serialize(new RedisCacheItem <TValue>(value, expiration == null ? NeverExpired.Instance : expiration()));
                _client.HSet(_cacheKey, sKey, content);
                return value;
            }));
        }