修复一些bug
This commit is contained in:
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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
Reference in new issue
Block a user