修复一些bug

This commit is contained in:
chfei committed 2026-11-10 09:54:12 +08:00
1 parent 9bb17a67d2
commit f4913b4fc2
7 files changed
+38 -10

No files matched your search

@@ -8,6 +8,7 @@
"MinimumLevel": {
"Default": "Debug",
"Override": {
"MAX.Framework.Security.TokenAuthenticationHandler": "Information",
"Microsoft": "Information",
"Microsoft.AspNetCore": "Warning",
"System": "Warning",
@@ -36,11 +36,6 @@ namespace Store.Modules.CloudProduct
// 服务自行创建客户端,单例复用连接池并由容器负责释放。
services.AddSingleton<ImageAnalysisQuotaService>();
// 图片识别沿用专用缓存库,所有请求共享并发上限。
var inspectionConnection = RequireConfiguration("ProductInspection:ConnectionString");
services.AddKeyedSingleton<IFreeSql>("ProductInspectionConnection", (_, _) =>
new FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.MySql, inspectionConnection)
.UseAdoConnectionPool(true).Build());
var maximum = Context.Configuration.GetValue<int?>("ProductInspection:MaxConcurrentAnalysis") ?? 5;
if (maximum is < 1 or > 100) throw new InvalidOperationException("识别并发数必须在 1 至 100 之间。");
services.AddKeyedSingleton<SemaphoreSlim>("ProductInspectionAnalysisGate", (_, _) => new SemaphoreSlim(maximum, maximum));
@@ -86,6 +86,22 @@ namespace Store.Modules.CloudProduct.Controllers
{
await _goodsIndexJob.ProcessPendingAsync();
}
/// <summary>循环处理数据库中待分词的正常商品,成功写入索引后标记 is_segmented=1。</summary>
[HttpGet]
[EndpointSummary("重建所有待处理商品索引")]
public async Task<long> RebuildPendingIndex()
{
long count = 0;
int batchCount;
do
{
batchCount = await _goodsService.IndexPendingGoodsAsync(1000);
count += batchCount;
} while (batchCount > 0);
return count;
}
/// <summary>
/// 分页搜索商品,可按标题、价格、类目、销量和平台筛选。
/// </summary>
@@ -112,9 +112,22 @@ public class GoodsViolationRepository(
public async Task InsertLogsAsync(GoodsViolationLogEntity[] logs)
{
// 即使 ORM 拆分 INSERT,各批次也在同一事务内提交。
using var unit = Orm.CreateUnitOfWork();
await unit.GetRepository<GoodsViolationLogEntity>().InsertAsync(logs);
unit.GetOrBeginTransaction();
foreach (var log in logs)
{
try
{
await unit.Orm.Insert(log).ExecuteAffrowsAsync();
}
catch (Exception ex) when (ex.GetBaseException() is MySql.Data.MySqlClient.MySqlException { Number: 1062 } duplicate
&& (duplicate.Message.EndsWith(".ux_violation_log_event'", StringComparison.Ordinal)
|| duplicate.Message.EndsWith("'ux_violation_log_event'", StringComparison.Ordinal)))
{
// 事件唯一键已存在即视为上报成功,保留首次记录,继续写入本批其他事件。
continue;
}
}
unit.Commit();
}
-1
View File
@@ -25,6 +25,5 @@
"Model": "qwen3.7-flash",
"ApiKey": "sk-fa7fbaa3bb4047928f30bf05ff52c03a",
"MaxConcurrentAnalysis": 5,
"ConnectionString": "Server=192.168.0.200;Port=3306;Database=product_inspection;Uid=root;Pwd=123456;Allow User Variables=true"
}
}
+1 -1
View File
@@ -6,7 +6,7 @@
}
},
"ConnectionStrings": {
"DefaultConnection": "Server=192.168.0.200;Port=3306;Database=mysql;Uid=root;Pwd=123456;",
"DefaultConnection": "Max Pool Size=512;Database='kjd';Data Source='nj-cynosdbmysql-grp-hl51pkfr.sql.tencentcdb.com';Port=27660;User Id='kjd';Password='Temukjd0625';Charset=utf8mb4;"
},
// 登录认证:请求头使用 Authorization: Bearer <accessToken>。
"TokenAuth": {
@@ -124,12 +124,16 @@ internal static class IntegrationChecks
Check(!await db.Select<GoodsViolationLogEntity>().Where(x => x.GoodsId == first).AnyAsync(), "reporting alone creates no log");
await violations.RecordLogsAsync([
new() { ShopId = "shop-a", GoodsId = first, ReasonId = (int)existingReasonId, Action = ViolationLogAction.Report },
]);
await violations.RecordLogsAsync([
new() { ShopId = "shop-a", GoodsId = first, ReasonId = (int)existingReasonId, Action = ViolationLogAction.Report },
new() { ShopId = "shop-c", GoodsId = first, ReasonId = (int)ignoredReasonId, Action = ViolationLogAction.Report },
new() { ShopId = "shop-c", GoodsId = first, ReasonId = (int)ignoredReasonId, Action = ViolationLogAction.Report }
]);
var reportLogs = await violations.GetLogsAsync(["shop-a", "shop-c"], first, 0, 50);
Check(reportLogs.Count == 2 && reportLogs.All(x => x.Action == ViolationLogAction.Report)
&& reportLogs.Any(x => x.ShopId == "shop-a" && x.ReasonId == existingReasonId)
&& reportLogs.Any(x => x.ShopId == "shop-c" && x.ReasonId == ignoredReasonId), "keep report source and ignored reasons");
&& reportLogs.Any(x => x.ShopId == "shop-c" && x.ReasonId == ignoredReasonId), "skip existing and in-batch duplicate events while keeping new events and their sources");
foreach (var action in new[] { ViolationLogAction.AutoListingExcluded, ViolationLogAction.AutoOffShelf })
await violations.RecordLogsAsync([new() { ShopId = "shop-b", GoodsId = first, ReasonId = (int)existingReasonId, Action = action }]);
var latest = (await violations.GetLogsAsync(["shop-b"], first, 0, 1)).Single();