增加 图片识别 缓存,缓存日期有等级
This commit is contained in:
1 parent
150e8644b7
commit
9bb17a67d2
5 files changed
+176
-19
No files matched your search
@@ -1,12 +1,86 @@
|
||||
using System.Text.Json;
|
||||
using Store.Modules.CloudProduct.Entities;
|
||||
|
||||
using var config = JsonDocument.Parse(File.ReadAllText("Plugins/CloudProduct/appsettings.json"));
|
||||
// 使用固定时间验证过期边界,无需等待或连接数据库。
|
||||
var now = DateTime.UtcNow;
|
||||
var cache = new ImageAnalysisCache { UpdatedAt = now, RecognitionResult = "[]" };
|
||||
foreach (var days in new[] { 1, 2, 4, 8, 16, 16 })
|
||||
{
|
||||
cache.RecordExpiration(true, now);
|
||||
if (cache.ExpiresAt != days * 24
|
||||
|| cache.ReadFreshResult(now.AddDays(days).AddTicks(-1)) is not { Length: 0 }
|
||||
|| cache.ReadFreshResult(now.AddDays(days)) != null)
|
||||
throw new Exception("连续空识别结果的缓存期限错误。");
|
||||
now = now.AddDays(days);
|
||||
}
|
||||
cache.RecognitionResult = """["文字"]""";
|
||||
cache.RecordExpiration(false, now);
|
||||
if (cache.ExpiresAt != 720
|
||||
|| cache.ReadFreshResult(now.AddDays(30).AddTicks(-1)) is not ["文字"]
|
||||
|| cache.ReadFreshResult(now.AddDays(30)) != null)
|
||||
throw new Exception("非空识别结果应重置级别并缓存三十天。");
|
||||
cache.RecognitionResult = "{}";
|
||||
if (cache.ReadFreshResult(now) != null)
|
||||
throw new Exception("旧对象格式应立即重新识别。");
|
||||
cache.RecordExpiration(true, now.AddDays(30));
|
||||
if (cache.ExpiresAt != 24)
|
||||
throw new Exception("非空结果后的首次空结果应重新从一天开始。");
|
||||
if (args.Contains("--cache-policy"))
|
||||
{
|
||||
Console.WriteLine("PASS cache expiration checks");
|
||||
return;
|
||||
}
|
||||
|
||||
using var config = JsonDocument.Parse(File.ReadAllText("Plugins/CloudProduct/appsettings.json"), new JsonDocumentOptions { CommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
|
||||
const string tableQuery = "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME";
|
||||
const string columnsQuery = "SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'image_analysis_cache' ORDER BY ORDINAL_POSITION";
|
||||
if (args.Contains("--migrate-cache-expiration"))
|
||||
{
|
||||
// 运行时缓存使用 CloudProductConnection;历史初始化命令仍针对原专用库。
|
||||
var cacheConnection = Environment.GetEnvironmentVariable("Plugins__CloudProduct__CloudProductConnection")
|
||||
?? config.RootElement.GetProperty("CloudProductConnection").GetString();
|
||||
using var cacheDb = new FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.MySql, cacheConnection).Build();
|
||||
const string expirationTypeQuery = """
|
||||
SELECT DATA_TYPE FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'image_analysis_cache' AND COLUMN_NAME = 'ExpiresAt'
|
||||
""";
|
||||
var columns = await cacheDb.Ado.QueryAsync<string>(columnsQuery);
|
||||
var expirationType = (await cacheDb.Ado.QueryAsync<string>(expirationTypeQuery)).SingleOrDefault();
|
||||
Console.WriteLine($"Cache columns before migration: {string.Join(", ", columns)}; ExpiresAt: {expirationType ?? "absent"}");
|
||||
if (!columns.Contains("RecognitionResult") || !columns.Contains("UpdatedAt"))
|
||||
throw new InvalidOperationException("当前运行库缺少缓存表或基础列。");
|
||||
if (expirationType is not (null or "int" or "datetime" or "timestamp"))
|
||||
throw new InvalidOperationException("不支持的 ExpiresAt 字段类型。");
|
||||
// 用临时列完成日期到时长的转换,回填完成后才一次性替换原列。
|
||||
var hasDateColumn = expirationType is "datetime" or "timestamp";
|
||||
var hoursColumn = hasDateColumn ? "ExpiresAtHours" : "ExpiresAt";
|
||||
if (!columns.Contains(hoursColumn))
|
||||
await cacheDb.Ado.ExecuteNonQueryAsync($"ALTER TABLE image_analysis_cache ADD {hoursColumn} INT NULL");
|
||||
// 已有整数时长原样保留;旧日期列按原到期时间与更新时间的差值换算。
|
||||
var initialHours = "IF(TRIM(RecognitionResult) = '[]', 24, 720)";
|
||||
if (hasDateColumn)
|
||||
initialHours = $"COALESCE(TIMESTAMPDIFF(HOUR, UpdatedAt, ExpiresAt), {initialHours})";
|
||||
await cacheDb.Ado.ExecuteNonQueryAsync($"UPDATE image_analysis_cache SET {hoursColumn} = {initialHours} WHERE {hoursColumn} IS NULL");
|
||||
if (hasDateColumn)
|
||||
await cacheDb.Ado.ExecuteNonQueryAsync("ALTER TABLE image_analysis_cache DROP COLUMN ExpiresAt, CHANGE ExpiresAtHours ExpiresAt INT NOT NULL");
|
||||
else if ((await cacheDb.Ado.QueryAsync<string>("SELECT IS_NULLABLE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'image_analysis_cache' AND COLUMN_NAME = 'ExpiresAt'")).Single() == "YES")
|
||||
await cacheDb.Ado.ExecuteNonQueryAsync("ALTER TABLE image_analysis_cache MODIFY ExpiresAt INT NOT NULL");
|
||||
|
||||
var finalType = (await cacheDb.Ado.QueryAsync<string>(expirationTypeQuery)).Single();
|
||||
var invalidRows = Convert.ToInt64(await cacheDb.Ado.ExecuteScalarAsync("""
|
||||
SELECT COUNT(*) FROM image_analysis_cache
|
||||
WHERE ExpiresAt IS NULL OR ExpiresAt NOT IN (24, 48, 96, 192, 384, 720)
|
||||
"""));
|
||||
if (finalType != "int" || invalidRows != 0)
|
||||
throw new InvalidOperationException($"迁移校验失败,ExpiresAt 类型 {finalType},异常行数 {invalidRows}。");
|
||||
if (columns.Contains("EmptyResultStreak"))
|
||||
await cacheDb.Ado.ExecuteNonQueryAsync("ALTER TABLE image_analysis_cache DROP COLUMN EmptyResultStreak");
|
||||
Console.WriteLine("PASS database migration: cache lifetime stored in ExpiresAt hours");
|
||||
return;
|
||||
}
|
||||
var connection = Environment.GetEnvironmentVariable("Plugins__CloudProduct__ProductInspection__ConnectionString")
|
||||
?? config.RootElement.GetProperty("ProductInspection").GetProperty("ConnectionString").GetString();
|
||||
using var db = new FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.MySql, connection).Build();
|
||||
const string tableQuery = "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME";
|
||||
const string columnsQuery = "SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'image_analysis_cache' ORDER BY ORDINAL_POSITION";
|
||||
if (args.Contains("--initialize"))
|
||||
{
|
||||
// 旧表只移除两个派生字段,保留缓存键、响应原文及更新时间。
|
||||
@@ -30,7 +104,7 @@ var cacheColumns = await db.Ado.QueryAsync<string>(columnsQuery);
|
||||
Console.WriteLine("Cache columns: " + string.Join(", ", cacheColumns));
|
||||
Console.WriteLine($"Cache rows: {await db.Select<ImageAnalysisCache>().CountAsync()}");
|
||||
if (args.Contains("--schema")) return;
|
||||
if (!cacheColumns.ToHashSet().SetEquals(new[] { "CacheKey", "RecognitionResult", "UpdatedAt" }))
|
||||
if (!cacheColumns.ToHashSet().SetEquals(new[] { "CacheKey", "RecognitionResult", "UpdatedAt", "ExpiresAt" }))
|
||||
throw new Exception("图片识别缓存结构不匹配。");
|
||||
if (!tables.Contains("image_analysis_cache"))
|
||||
throw new Exception("商品检测专用库缺少图片缓存表。");
|
||||
|
||||
Reference in new issue
Block a user