2025-06-14 22:12:37 +08:00
|
|
|
|
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]
|
2025-06-16 20:12:35 +08:00
|
|
|
|
public class TaskStatusCheckService(ITokenService tokenService, ApplicationDbContext dbContext, ILogger<TaskStatusCheckService> logger, ITaskService taskService, ITaskConcurrencyManager taskConcurrencyManager, TokenUsageTracker tokenUsageTracker) : IJob
|
2025-06-14 22:12:37 +08:00
|
|
|
|
{
|
|
|
|
|
|
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;
|
2025-06-16 20:12:35 +08:00
|
|
|
|
private readonly TokenUsageTracker _tokenUsageTracker = tokenUsageTracker;
|
2025-06-14 22:12:37 +08:00
|
|
|
|
|
|
|
|
|
|
public async Task Execute(IJobExecutionContext context)
|
|
|
|
|
|
{
|
2025-06-21 14:41:21 +08:00
|
|
|
|
_logger.LogInformation($"开始检查TASK信息 - 检查间隔: 20 秒,同步加载 原始请求的Token!");
|
2025-06-14 22:12:37 +08:00
|
|
|
|
|
|
|
|
|
|
var startTime = BeijingTimeExtension.GetBeijingTime();
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
2025-06-16 20:12:35 +08:00
|
|
|
|
// 强制同步数据库数据,原请求Token
|
2025-06-14 22:12:37 +08:00
|
|
|
|
await _tokenService.LoadOriginTokenAsync();
|
|
|
|
|
|
|
2025-06-16 20:12:35 +08:00
|
|
|
|
// 强制同步数据 MJ API 的 Basic URL
|
|
|
|
|
|
|
|
|
|
|
|
await _tokenService.LoadMJAPIBasicUrlAsync();
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-06-14 22:12:37 +08:00
|
|
|
|
// 检查Task状态和返回值
|
|
|
|
|
|
// 获取所有超过五分钟没有完成的人物
|
2025-06-21 14:41:21 +08:00
|
|
|
|
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();
|
2025-06-14 22:12:37 +08:00
|
|
|
|
|
|
|
|
|
|
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);
|
2025-06-16 20:12:35 +08:00
|
|
|
|
// 尝试释放 当前缓存中的任务
|
|
|
|
|
|
_tokenUsageTracker.RemoveTaskCache(task.ThirdPartyTaskId);
|
|
|
|
|
|
_logger.LogWarning("任务轮询检查,未请求到对应的MJ数据,释放Token,释放任务" + task.Token);
|
|
|
|
|
|
_tokenUsageTracker.ReleaseConcurrencyPermit(task.Token);
|
2025-06-14 22:12:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
2025-06-27 10:45:19 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-21 22:22:54 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-06-14 22:12:37 +08:00
|
|
|
|
if (status == MJTaskStatus.SUCCESS || status == MJTaskStatus.FAILURE || status == MJTaskStatus.CANCEL)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 当前任务已经被释放过了
|
|
|
|
|
|
// 开始修改数据
|
|
|
|
|
|
task.EndTime = BeijingTimeExtension.GetBeijingTime();
|
|
|
|
|
|
task.Properties = JsonConvert.SerializeObject(properties);
|
2025-06-16 20:12:35 +08:00
|
|
|
|
_logger.LogInformation("任务轮询检查,已请求到对应的MJ数据,并且状态为成功,失败,取消,释放Token,释放任务" + task.Token);
|
|
|
|
|
|
_tokenUsageTracker.ReleaseConcurrencyPermit(task.Token);
|
|
|
|
|
|
// 尝试释放 当前缓存中的任务
|
|
|
|
|
|
_tokenUsageTracker.RemoveTaskCache(task.ThirdPartyTaskId);
|
2025-06-14 22:12:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// 任务还在处理中
|
|
|
|
|
|
task.EndTime = null; // 处理中没有结束时间
|
|
|
|
|
|
task.Properties = JsonConvert.SerializeObject(properties);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 开始修改数据
|
|
|
|
|
|
await _taskConcurrencyManager.UpdateTaskInDatabase(task);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 报错
|
2025-06-16 20:12:35 +08:00
|
|
|
|
_logger.LogError(ex, $"检查任务 {task.Token} 时发生错误,释放Token,释放任务", task.TaskId);
|
2025-06-14 22:12:37 +08:00
|
|
|
|
task.Status = MJTaskStatus.FAILURE;
|
|
|
|
|
|
var newProperties = new
|
|
|
|
|
|
{
|
|
|
|
|
|
failReason = "任务报错"
|
|
|
|
|
|
};
|
|
|
|
|
|
task.EndTime = BeijingTimeExtension.GetBeijingTime();
|
|
|
|
|
|
task.Properties = JsonConvert.SerializeObject(newProperties);
|
2025-06-16 20:12:35 +08:00
|
|
|
|
_tokenUsageTracker.ReleaseConcurrencyPermit(task.Token);
|
|
|
|
|
|
// 尝试释放 当前缓存中的任务
|
|
|
|
|
|
_tokenUsageTracker.RemoveTaskCache(task.ThirdPartyTaskId);
|
2025-06-14 22:12:37 +08:00
|
|
|
|
// 开始修改数据
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-21 22:22:54 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-06-27 10:45:19 +08:00
|
|
|
|
/// 合作伙伴任务数据处理
|
2025-06-21 22:22:54 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="properties"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-06-27 10:45:19 +08:00
|
|
|
|
public Dictionary<string, object> ProcessPartnerTaskDataAsync(Dictionary<string, object> properties)
|
2025-06-21 22:22:54 +08:00
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
string jsonStr = JsonConvert.SerializeObject(properties);
|
2025-06-27 10:45:19 +08:00
|
|
|
|
dynamic data = JsonConvert.DeserializeObject(jsonStr) ?? new object { };
|
2025-06-21 22:22:54 +08:00
|
|
|
|
|
|
|
|
|
|
// 检查是否是合作伙伴任务
|
2025-06-27 10:45:19 +08:00
|
|
|
|
// 直接用dynamic访问,不做类型判断
|
|
|
|
|
|
bool isPartner = data?.isPartner ?? false;
|
|
|
|
|
|
string partnerTaskId = data?.partnerTaskId ?? string.Empty;
|
2025-06-21 22:22:54 +08:00
|
|
|
|
|
|
|
|
|
|
if (isPartner && !string.IsNullOrEmpty(partnerTaskId))
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.LogInformation($"处理合作伙伴任务: {partnerTaskId}");
|
|
|
|
|
|
|
2025-06-27 10:45:19 +08:00
|
|
|
|
// 直接遍历,让异常处理兜底
|
|
|
|
|
|
var imageUrls = new List<object>();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var item in data?.partnerTaskInfo?.imgUrls ?? Array.Empty<object>())
|
2025-06-21 22:22:54 +08:00
|
|
|
|
{
|
2025-06-27 10:45:19 +08:00
|
|
|
|
string url = item?.url ?? string.Empty;
|
|
|
|
|
|
if (!string.IsNullOrEmpty(url))
|
2025-06-21 22:22:54 +08:00
|
|
|
|
{
|
2025-06-27 10:45:19 +08:00
|
|
|
|
imageUrls.Add(new { url });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-21 22:22:54 +08:00
|
|
|
|
|
2025-06-27 10:45:19 +08:00
|
|
|
|
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 });
|
2025-06-21 22:22:54 +08:00
|
|
|
|
}
|
2025-06-27 10:45:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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))
|
2025-06-21 22:22:54 +08:00
|
|
|
|
{
|
2025-06-27 10:45:19 +08:00
|
|
|
|
imageUrls.Add(new { url });
|
2025-06-21 22:22:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-27 10:45:19 +08:00
|
|
|
|
|
|
|
|
|
|
if (imageUrls.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
properties["imageUrls"] = imageUrls;
|
|
|
|
|
|
_logger.LogInformation($"成功提取了{imageUrls.Count}个图片URL");
|
|
|
|
|
|
}
|
2025-06-21 22:22:54 +08:00
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-06-27 10:45:19 +08:00
|
|
|
|
_logger.LogInformation("未找到youChuanTaskInfo或者是图片信信息");
|
2025-06-21 22:22:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-06-27 10:45:19 +08:00
|
|
|
|
_logger.LogInformation($"任务不是YouChuan任务或缺少必要信息: isYouChuan={isYouChuan}, youChuanTaskId={youChuanTaskId}");
|
2025-06-21 22:22:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return properties;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.LogError(ex, "处理任务数据时发生错误");
|
|
|
|
|
|
return properties; // 返回原始数据,避免处理错误导致数据丢失
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-14 22:12:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|