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

327 lines
15 KiB
C#
Raw Permalink 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 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;
if (properties.TryGetValue("isPartner", out var isPartner))
{
if ((bool)isPartner == true)
{
properties = ProcessPartnerTaskDataAsync(properties);
}
}
else if (properties.TryGetValue("isOfficial", out var isOfficial))
{
if ((bool)isOfficial == true)
{
properties = ProcessOfficialTaskDataAsync(properties);
}
}
else if (properties.TryGetValue("isYouChuan", out var isYouChuan))
{
if ((bool)isYouChuan == true)
{
properties = ProcessYouChuanTaskDataAsync(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>
/// 合作伙伴任务数据处理
/// </summary>
/// <param name="properties"></param>
/// <returns></returns>
public Dictionary<string, object> ProcessPartnerTaskDataAsync(Dictionary<string, object> properties)
{
try
{
string jsonStr = JsonConvert.SerializeObject(properties);
dynamic data = JsonConvert.DeserializeObject(jsonStr) ?? new object { };
// 检查是否是合作伙伴任务
// 直接用dynamic访问不做类型判断
bool isPartner = data?.isPartner ?? false;
string partnerTaskId = data?.partnerTaskId ?? string.Empty;
if (isPartner && !string.IsNullOrEmpty(partnerTaskId))
{
_logger.LogInformation($"处理合作伙伴任务: {partnerTaskId}");
// 直接遍历,让异常处理兜底
var imageUrls = new List<object>();
foreach (var item in data?.partnerTaskInfo?.imgUrls ?? Array.Empty<object>())
{
string url = item?.url ?? string.Empty;
if (!string.IsNullOrEmpty(url))
{
imageUrls.Add(new { url });
}
}
if (imageUrls.Count > 0)
{
properties["imageUrls"] = imageUrls;
_logger.LogInformation($"成功提取了{imageUrls.Count}个图片URL");
}
else
{
_logger.LogInformation("未找到partnerTaskInfo或者是图片信信息");
}
}
else
{
_logger.LogInformation($"任务不是partner任务或缺少必要信息: isPartner={isPartner}, partnerTaskId={partnerTaskId}");
}
return properties;
}
catch (Exception ex)
{
_logger.LogError(ex, "处理任务数据时发生错误");
return properties; // 返回原始数据,避免处理错误导致数据丢失
}
}
/// <summary>
/// 官方任务数据处理
/// </summary>
/// <param name="properties"></param>
/// <returns></returns>
public Dictionary<string, object> ProcessOfficialTaskDataAsync(Dictionary<string, object> properties)
{
try
{
string jsonStr = JsonConvert.SerializeObject(properties);
dynamic data = JsonConvert.DeserializeObject(jsonStr) ?? new object { };
// 检查是否是合作伙伴任务
// 直接用dynamic访问不做类型判断
bool isOfficial = data?.isOfficial ?? false;
string officialTaskId = data?.officialTaskId ?? string.Empty;
if (isOfficial && !string.IsNullOrEmpty(officialTaskId))
{
_logger.LogInformation($"处理官方任务: {officialTaskId}");
// 直接遍历,让异常处理兜底
var imageUrls = new List<object>();
foreach (var item in data?.officialTaskInfo?.imgUrls ?? Array.Empty<object>())
{
string url = item?.url ?? string.Empty;
if (!string.IsNullOrEmpty(url))
{
imageUrls.Add(new { url });
}
}
if (imageUrls.Count > 0)
{
properties["imageUrls"] = imageUrls;
_logger.LogInformation($"成功提取了{imageUrls.Count}个图片URL");
}
else
{
_logger.LogInformation("未找到officialTaskInfo或者是图片信信息");
}
}
else
{
_logger.LogInformation($"任务不是official任务或缺少必要信息: isOfficial={isOfficial}, officialTaskId={officialTaskId}");
}
return properties;
}
catch (Exception ex)
{
_logger.LogError(ex, "处理任务数据时发生错误");
return properties; // 返回原始数据,避免处理错误导致数据丢失
}
}
/// <summary>
/// 悠船任务数据处理
/// </summary>
/// <param name="properties"></param>
/// <returns></returns>
public Dictionary<string, object> ProcessYouChuanTaskDataAsync(Dictionary<string, object> properties)
{
try
{
string jsonStr = JsonConvert.SerializeObject(properties);
dynamic data = JsonConvert.DeserializeObject(jsonStr) ?? new object { };
// 检查是否是合作伙伴任务
// 直接用dynamic访问不做类型判断
bool isYouChuan = data?.isYouChuan ?? false;
string youChuanTaskId = data?.youChuanTaskId ?? string.Empty;
if (isYouChuan && !string.IsNullOrEmpty(youChuanTaskId))
{
_logger.LogInformation($"处理悠船任务: {youChuanTaskId}");
// 直接遍历,让异常处理兜底
var imageUrls = new List<object>();
foreach (var item in data?.youChuanTaskInfo?.imgUrls ?? Array.Empty<object>())
{
string url = item?.url ?? string.Empty;
if (!string.IsNullOrEmpty(url))
{
imageUrls.Add(new { url });
}
}
if (imageUrls.Count > 0)
{
properties["imageUrls"] = imageUrls;
_logger.LogInformation($"成功提取了{imageUrls.Count}个图片URL");
}
else
{
_logger.LogInformation("未找到youChuanTaskInfo或者是图片信信息");
}
}
else
{
_logger.LogInformation($"任务不是YouChuan任务或缺少必要信息: isYouChuan={isYouChuan}, youChuanTaskId={youChuanTaskId}");
}
return properties;
}
catch (Exception ex)
{
_logger.LogError(ex, "处理任务数据时发生错误");
return properties; // 返回原始数据,避免处理错误导致数据丢失
}
}
}
}