LMS.service/LMS.Tools/MJPackage/TaskStatusCheckService.cs
lq1405 3470ce9229 v 1.1.5
修改轮询请求逻辑 添加imageUrls属性,通过第三方生成
修改 mj fetch,不转发API 而是用系统的数据
2025-06-21 22:22:54 +08:00

207 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using LMS.Common.Extensions;
using LMS.DAO;
using LMS.Repository.DB;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Quartz;
namespace LMS.Tools.MJPackage
{
[DisallowConcurrentExecution]
public class TaskStatusCheckService(ITokenService tokenService, ApplicationDbContext dbContext, ILogger<TaskStatusCheckService> logger, ITaskService taskService, ITaskConcurrencyManager taskConcurrencyManager, TokenUsageTracker tokenUsageTracker) : IJob
{
private readonly ITokenService _tokenService = tokenService;
private readonly ApplicationDbContext _dbContext = dbContext;
private readonly ILogger<TaskStatusCheckService> _logger = logger;
private readonly ITaskService _taskService = taskService;
private readonly ITaskConcurrencyManager _taskConcurrencyManager = taskConcurrencyManager;
private readonly TokenUsageTracker _tokenUsageTracker = tokenUsageTracker;
public async Task Execute(IJobExecutionContext context)
{
_logger.LogInformation($"开始检查TASK信息 - 检查间隔: 20 秒,同步加载 原始请求的Token");
var startTime = BeijingTimeExtension.GetBeijingTime();
try
{
// 强制同步数据库数据原请求Token
await _tokenService.LoadOriginTokenAsync();
// 强制同步数据 MJ API 的 Basic URL
await _tokenService.LoadMJAPIBasicUrlAsync();
// 检查Task状态和返回值
// 获取所有超过五分钟没有完成的人物
List<MJApiTasks> tasks = await _dbContext.MJApiTasks.Where(t => t.Status != MJTaskStatus.CANCEL && t.Status != MJTaskStatus.SUCCESS && t.Status != MJTaskStatus.FAILURE && t.StartTime < BeijingTimeExtension.GetBeijingTime()).ToListAsync();
if (tasks.Count == 0)
{
_logger.LogInformation("没有需要检查的任务!");
return;
}
// 开始每个请求
foreach (MJApiTasks task in tasks)
{
try
{
Dictionary<string, object>? properties = await _taskService.FetchTaskAsync(task);
// 没有找到数据的
if (properties == null)
{
// 没有找到数据 直接把任务失败
task.Status = MJTaskStatus.FAILURE;
var newProperties = new
{
failReason = "任务丢失或未找到"
};
task.EndTime = BeijingTimeExtension.GetBeijingTime();
task.Properties = JsonConvert.SerializeObject(newProperties);
// 尝试释放 当前缓存中的任务
_tokenUsageTracker.RemoveTaskCache(task.ThirdPartyTaskId);
_logger.LogWarning("任务轮询检查未请求到对应的MJ数据释放Token释放任务" + task.Token);
_tokenUsageTracker.ReleaseConcurrencyPermit(task.Token);
}
else
{
// 尝试获取状态字段
string status = MJTaskStatus.SUBMITTED;
if (properties.TryGetValue("status", out var statusElement))
{
status = statusElement.ToString() ?? MJTaskStatus.SUBMITTED;
}
else if (properties.TryGetValue("Status", out var statusElementCap))
{
status = statusElementCap.ToString() ?? MJTaskStatus.SUBMITTED;
}
task.Status = status;
properties = ProcessTaskDataAsync(properties);
if (status == MJTaskStatus.SUCCESS || status == MJTaskStatus.FAILURE || status == MJTaskStatus.CANCEL)
{
// 当前任务已经被释放过了
// 开始修改数据
task.EndTime = BeijingTimeExtension.GetBeijingTime();
task.Properties = JsonConvert.SerializeObject(properties);
_logger.LogInformation("任务轮询检查已请求到对应的MJ数据并且状态为成功失败取消释放Token释放任务" + task.Token);
_tokenUsageTracker.ReleaseConcurrencyPermit(task.Token);
// 尝试释放 当前缓存中的任务
_tokenUsageTracker.RemoveTaskCache(task.ThirdPartyTaskId);
}
else
{
// 任务还在处理中
task.EndTime = null; // 处理中没有结束时间
task.Properties = JsonConvert.SerializeObject(properties);
}
}
// 开始修改数据
await _taskConcurrencyManager.UpdateTaskInDatabase(task);
}
catch (Exception ex)
{
// 报错
_logger.LogError(ex, $"检查任务 {task.Token} 时发生错误释放Token释放任务", task.TaskId);
task.Status = MJTaskStatus.FAILURE;
var newProperties = new
{
failReason = "任务报错"
};
task.EndTime = BeijingTimeExtension.GetBeijingTime();
task.Properties = JsonConvert.SerializeObject(newProperties);
_tokenUsageTracker.ReleaseConcurrencyPermit(task.Token);
// 尝试释放 当前缓存中的任务
_tokenUsageTracker.RemoveTaskCache(task.ThirdPartyTaskId);
// 开始修改数据
await _taskConcurrencyManager.UpdateTaskInDatabase(task);
}
}
var duration = BeijingTimeExtension.GetBeijingTime() - startTime;
_logger.LogInformation($"Task状态检查完成影响的Task {tasks.Count},耗时: {duration}ms", duration.TotalMilliseconds);
}
catch (Exception ex)
{
var duration = BeijingTimeExtension.GetBeijingTime() - startTime;
_logger.LogError(ex, "Token同步失败耗时: {Duration}ms", duration.TotalMilliseconds);
}
}
/// <summary>
/// 单独处理生图包将参数xie'chu'l
/// </summary>
/// <param name="properties"></param>
/// <returns></returns>
public Dictionary<string, object> ProcessTaskDataAsync(Dictionary<string, object> properties)
{
try
{
// 转换为JObject以简化访问
string jsonStr = JsonConvert.SerializeObject(properties);
JObject jObj = JObject.Parse(jsonStr);
// 检查是否是合作伙伴任务
bool isPartner = jObj["isPartner"]?.Value<bool>() ?? false;
string? partnerTaskId = jObj["partnerTaskId"]?.ToString();
if (isPartner && !string.IsNullOrEmpty(partnerTaskId))
{
_logger.LogInformation($"处理合作伙伴任务: {partnerTaskId}");
// 获取partnerTaskInfo和imgUrls
JToken? partnerTaskInfo = jObj["partnerTaskInfo"];
if (partnerTaskInfo != null)
{
if (partnerTaskInfo["imgUrls"] is JArray imgUrlsArray && imgUrlsArray.Count > 0)
{
var imageUrls = new List<object>();
foreach (JToken item in imgUrlsArray)
{
string? url = item["url"]?.ToString();
if (!string.IsNullOrEmpty(url))
{
imageUrls.Add(new
{
url = url ?? string.Empty
});
}
}
if (imageUrls.Count > 0)
{
// 直接添加到原始properties字典
properties["imgUrls"] = imageUrls;
_logger.LogInformation($"成功提取了{imageUrls.Count}个图片URL");
}
}
else
{
_logger.LogInformation("未找到图片URL数组或数组为空");
}
}
else
{
_logger.LogInformation("未找到partnerTaskInfo信息");
}
}
else
{
_logger.LogInformation($"任务不是partner任务或缺少必要信息: isPartner={isPartner}, partnerTaskId={partnerTaskId}");
}
return properties;
}
catch (Exception ex)
{
_logger.LogError(ex, "处理任务数据时发生错误");
return properties; // 返回原始数据,避免处理错误导致数据丢失
}
}
}
}