refactor(work-service,print-worker): 优化代码结构与错误处理

1. 提取评分prompt构建逻辑减少重复代码
2. 移除冗余的参考答案图片循环逻辑
3. 重构打印服务的错误回调逻辑,统一失败处理流程
4. 新增打印服务的任务取消处理逻辑
This commit is contained in:
glz
2026-07-08 17:07:41 +08:00
parent 195792ec66
commit de9a0c2978
3 changed files with 45 additions and 37 deletions

View File

@ -47,10 +47,11 @@ public class AutoDotCodeConsumer(
using var scope = scopeFactory.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
JournalPagePrintDto? request = null;
try
{
var request = JsonSerializer.Deserialize<JournalPagePrintDto>(message, new JsonSerializerOptions
request = JsonSerializer.Deserialize<JournalPagePrintDto>(message, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
@ -72,6 +73,7 @@ public class AutoDotCodeConsumer(
if (string.IsNullOrWhiteSpace(journalPdfKey))
{
logger.LogError("书籍上传 PDF 文件地址为空JournalId: {JournalId}", request.JournalId);
await TryCallbackCodeFailAsync(request, cancellationToken);
return;
}
@ -79,6 +81,7 @@ public class AutoDotCodeConsumer(
if (pdfStream == null)
{
logger.LogError("获取书籍上传 PDF 文件失败OSS Key: {OssKey}", journalPdfKey);
await TryCallbackCodeFailAsync(request, cancellationToken);
return;
}
@ -93,6 +96,7 @@ public class AutoDotCodeConsumer(
if (dotFile == null)
{
logger.LogError("配置打印数据错误点阵文件不存在DotId: {DotId}", dotId);
await TryCallbackCodeFailAsync(request, cancellationToken);
return;
}
@ -101,7 +105,7 @@ public class AutoDotCodeConsumer(
if (!File.Exists(exePath))
{
logger.LogError("PrintTool.exe 不存在,路径:{ExePath}", exePath);
await ExecuteUpdateJournalStatusAsync(BuildFailResponse(request), cancellationToken);
await TryCallbackCodeFailAsync(request, cancellationToken);
return;
}
@ -109,7 +113,7 @@ public class AutoDotCodeConsumer(
if (!File.Exists(xmlPath))
{
logger.LogError("铺码授权文件不存在,路径:{XmlPath}", xmlPath);
await ExecuteUpdateJournalStatusAsync(BuildFailResponse(request), cancellationToken);
await TryCallbackCodeFailAsync(request, cancellationToken);
return;
}
@ -126,7 +130,7 @@ public class AutoDotCodeConsumer(
if (dotFileDetailList.Count < pageNumMax)
{
logger.LogError("点阵页码余量不足DotId: {DotId}, Need: {Need}, Available: {Available}", dotId, pageNumMax, dotFileDetailList.Count);
await ExecuteUpdateJournalStatusAsync(BuildFailResponse(request), cancellationToken);
await TryCallbackCodeFailAsync(request, cancellationToken);
return;
}
@ -138,7 +142,7 @@ public class AutoDotCodeConsumer(
if (printResult.Timeout || printResult.ExitCode != 0)
{
logger.LogError("执行 PrintTool.exe 失败,退出码:{ExitCode},错误信息:{ErrorMessage}", printResult.ExitCode, printResult.Error);
await ExecuteUpdateJournalStatusAsync(BuildFailResponse(request, dotFileDetailPageName), cancellationToken);
await TryCallbackCodeFailAsync(request, cancellationToken, dotFileDetailPageName);
return;
}
@ -150,8 +154,7 @@ public class AutoDotCodeConsumer(
if (!ValidatePrintOutput(printResult.Output, dotFileDetailPageName, dPrint))
{
statusModel.Status = JournalStatusEnum.CodeFail;
await ExecuteUpdateJournalStatusAsync(statusModel, cancellationToken);
await TryCallbackCodeFailAsync(request, cancellationToken, dotFileDetailPageName);
return;
}
@ -192,10 +195,18 @@ public class AutoDotCodeConsumer(
logger.LogError("回调接口修改书籍状态失败JournalId: {JournalId},接口返回消息:{Message}", statusModel.JournalId, callbackResponse.Message);
}
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
logger.LogWarning("自动铺码处理已取消JournalId: {JournalId}", request?.JournalId);
throw;
}
catch (Exception ex)
{
logger.LogError(ex, "自动铺码处理失败");
throw;
if (request != null)
{
await TryCallbackCodeFailAsync(request, CancellationToken.None);
}
}
}
@ -298,6 +309,26 @@ public class AutoDotCodeConsumer(
return new CallbackUpdateJournalStatusResponse();
}
private async Task TryCallbackCodeFailAsync(JournalPagePrintDto request, CancellationToken cancellationToken, string[]? pageNo = null)
{
try
{
var callbackResponse = await ExecuteUpdateJournalStatusAsync(BuildFailResponse(request, pageNo), cancellationToken);
if (!callbackResponse.IsSuccess)
{
logger.LogError("回调接口修改书籍为铺码失败状态失败JournalId: {JournalId},接口返回消息:{Message}", request.JournalId, callbackResponse.Message);
}
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
throw;
}
catch (Exception callbackEx)
{
logger.LogError(callbackEx, "铺码失败后请求回调接口失败JournalId: {JournalId}", request.JournalId);
}
}
private static JournalPagePrintDto BuildFailResponse(JournalPagePrintDto request, string[]? pageNo = null)
{
return new JournalPagePrintDto

View File

@ -233,13 +233,14 @@ public class JournalTaskReceiveConsumer(
{
throw new InvalidOperationException("AI聊天服务配置不完整请检查 AiChat 配置节点");
}
var answerMapPrompt = BuildScorePrompt(scoreUnit, referenceAnswerMap);
logger.LogInformation(answerMapPrompt);
var content = new List<object>
{
new
{
type = "text",
text = BuildScorePrompt(scoreUnit, referenceAnswerMap)
text = answerMapPrompt
}
};
@ -251,7 +252,7 @@ public class JournalTaskReceiveConsumer(
content.Add(new
{
type = "text",
text = $"以下为任务 {context.Task.Id} 的学生作答图片,共 {answerImages.Count} 张。"
text = $"以下学生作答图片,共 {answerImages.Count} 张。"
});
foreach (var answerImage in answerImages)
@ -269,31 +270,6 @@ public class JournalTaskReceiveConsumer(
throw new InvalidOperationException($"评分单元 {scoreUnit.GroupId} 缺少答案图片");
}
foreach (var context in scoreUnit.Questions)
{
referenceAnswerMap.TryGetValue(context.Task.Id, out var referenceAnswers);
var referenceAnswerImages = await BuildReferenceAnswerImageContentsAsync(context.Task.Id, referenceAnswers ?? [], cancellationToken);
if (referenceAnswerImages.Count == 0)
{
continue;
}
content.Add(new
{
type = "text",
text = $"以下为任务 {context.Task.Id} 的参考答案图片,共 {referenceAnswerImages.Count} 张。参考答案不是必有评分时以题目Prompt和学生答案为主。"
});
foreach (var referenceAnswerImage in referenceAnswerImages)
{
content.Add(new
{
type = "image_url",
image_url = new { url = referenceAnswerImage.DataUrl }
});
}
}
var requestBody = new
{
model,
@ -403,6 +379,7 @@ public class JournalTaskReceiveConsumer(
prompt.AppendLine(" \"Completion\": 100,");
prompt.AppendLine(" \"Result\": \"50字内的中文评语\"");
prompt.AppendLine("}");
return prompt.ToString();
}

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>