我们将serviceStack缓存与OrmLite提供者(MySql)结合使用。我们注意到,当我们创建带有到期日期的缓存密钥时,这些密钥在到期日期之后不会被删除。相反,它们在“ExpiryDate”列中获得空值。因此,在计算Cache.GetTimeToLive()时会产生奇怪的值。
这是serviceStack中的一个bug,还是键创建代码中的错误?我们使用的是ServiceStack版本(4.5.4)和OrmLite版本(4.5.4)
IAppSettings appSettings = new AppSettings();
var userConsultsPerHourLimit = appSettings.Get<int>("throttling:consultations:requests:perHourLimit");
var userConsultsPerDayLimit = appSettings.Get<int>("throttling:consultations:requests:perDayLimit");
var userConsultsPerMonthLimit = appSettings.Get<int>("throttling:consultations:requests:perMonthLimit");
var userConsultsMadePerHour = Cache.GetOrCreate<int>(UserConsultPerHourCacheKey, TimeSpan.FromHours(1), () => { return 0; });
var userConsultsMadePerDay = Cache.GetOrCreate<int>(UserConsultPerDayCacheKey, TimeSpan.FromDays(1), () => { return 0; });
var userConsultsMadePerMonth = Cache.GetOrCreate<int>(UserConsultPerMonthCacheKey, (new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, 1).AddMonths(1).AddDays(-1) - DateTime.UtcNow), () => { return 0; });
string retryAfter = System.Threading.Thread.CurrentThread.CurrentCulture.Name == "ar-SA" ? "يوم" : "day";
bool shouldThrottleRequest = false;
bool didExceedMonthlyLimit = false;
if (userConsultsMadePerHour >= userConsultsPerHourLimit)
{
shouldThrottleRequest = true;
TimeSpan? timeToLive = Cache.GetTimeToLive(UserConsultPerHourCacheKey);
if (timeToLive.HasValue)
retryAfter = Humanizer.TimeSpanHumanizeExtensions.Humanize(timeToLive.Value, 2, System.Threading.Thread.CurrentThread.CurrentUICulture);
}
else if (userConsultsMadePerDay >= userConsultsPerDayLimit)
{
shouldThrottleRequest = true;
TimeSpan? timeToLive = Cache.GetTimeToLive(UserConsultPerDayCacheKey);
if (timeToLive.HasValue)
retryAfter = Humanizer.TimeSpanHumanizeExtensions.Humanize(timeToLive.Value, 2, System.Threading.Thread.CurrentThread.CurrentUICulture);
}
else if (userConsultsMadePerMonth >= userConsultsPerMonthLimit)
{
shouldThrottleRequest = true;
TimeSpan? timeToLive = Cache.GetTimeToLive(UserConsultPerMonthCacheKey);
if (timeToLive.HasValue)
retryAfter = Humanizer.TimeSpanHumanizeExtensions.Humanize(timeToLive.Value, 3, System.Threading.Thread.CurrentThread.CurrentUICulture);
didExceedMonthlyLimit = true;
}发布于 2017-06-19 20:37:24
我想我们找到了真相..。这是由于我们一方对缓存API的误用造成的。我们在其他不同的地方发现了对"Increment“和”deleted“API的API调用,导致删除密钥(那些已经超过到期日期的密钥)(通过内部调用验证方法),然后从头重新创建(但没有终止日期)。解决方案是在调用Increment/ date之前调用GetOrCreate,以确保密钥确实存在,如果不存在,则使用新的过期日期值重新创建它。
发布于 2017-06-13 17:44:31
这是按预期工作,在ServiceStack的最新版本中,在获取过期的缓存条目后删除行:
var ormliteCache = Cache as OrmLiteCacheClient;
var key = "int:key";
var value = Cache.GetOrCreate(key, TimeSpan.FromMilliseconds(100), () => 1);
var ttl = Cache.GetTimeToLive(key);
using (var db = ormliteCache.DbFactory.OpenDbConnection())
{
var row = db.SingleById<CacheEntry>(key);
Assert.That(row, Is.Not.Null);
Assert.That(row.ExpiryDate, Is.Not.Null);
}
Assert.That(value, Is.EqualTo(1));
Assert.That(ttl.Value.TotalMilliseconds, Is.GreaterThan(0));
Thread.Sleep(200);
value = Cache.Get<int>(key);
ttl = Cache.GetTimeToLive(key);
Assert.That(value, Is.EqualTo(0));
Assert.That(ttl, Is.Null);
using (var db = ormliteCache.DbFactory.OpenDbConnection())
{
var row = db.SingleById<CacheEntry>(key);
Assert.That(row, Is.Null);
}我们注意到,当我们创建带有到期日期的缓存密钥时,这些密钥在到期日期之后不会被删除。
关系数据库管理系统不会按日期自动过期缓存条目,但是当解析缓存条目时,OrmLiteCacheClient将自动删除过期条目(如上文所示),因此它将永远不会返回过期的条目。
相反,它们在“ExpiryDate”列中获得空值。
这是不可能的只有在创建或替换现有条目时才填充ExpiryDate,它在过期时从未设置为null。当条目过期时,整个条目将被删除。
https://stackoverflow.com/questions/44524688
复制相似问题