LMS.service/LMS.Tools/MJPackage/TaskStatusCheckService.cs

207 lines
10 KiB
C#
Raw Normal View History

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; // 返回原始数据,避免处理错误导致数据丢失
}
}
}
}