148 lines
5.6 KiB
C#
Raw Normal View History


using LMS.Common.Extensions;
using LMS.DAO;
using LMS.Repository.DB;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace LMS.Tools.MJPackage
{
public class TaskService(ITokenService tokenService, ILogger<TaskService> logger, ApplicationDbContext dbContext, ITaskConcurrencyManager taskConcurrencyManager) : ITaskService
{
private readonly ITokenService _tokenService = tokenService;
private readonly ILogger<TaskService> _logger = logger;
private readonly ApplicationDbContext _dbContext = dbContext;
private readonly ITaskConcurrencyManager _taskConcurrencyManager = taskConcurrencyManager;
public async Task<Dictionary<string, object>?> FetchTaskAsync(MJApiTasks mJApiTasks)
{
try
{
// 获取UseToken先尝试 Token再尝试 TokenId
var tokenConfig = await _tokenService.GetTokenAsync(mJApiTasks.Token);
string useToken = string.Empty;
if (tokenConfig == null)
{
// Token 没找到 尝试用 TokenId 查找
MJApiTokens? mJApiTokens = await _tokenService.GetMJapiTokenByIdAsync(mJApiTasks.TokenId);
if (mJApiTokens == null)
{
return null;
}
useToken = mJApiTokens.UseToken;
}
else
{
useToken = tokenConfig.UseToken;
}
if (string.IsNullOrWhiteSpace(useToken))
{
_logger.LogInformation($"Token is empty for task ID: {mJApiTasks.TaskId}");
return null;
}
// 尝试备用API
var backupResult = await TryBackupApiAsync(mJApiTasks.ThirdPartyTaskId, useToken);
if (string.IsNullOrWhiteSpace(backupResult))
{
// 没有找到数据
_logger.LogInformation($"备用API没有返回数据TaskId: {mJApiTasks.TaskId}");
return null;
}
var properties = new Dictionary<string, object>();
try
{
// 不为空 开始解析数据
properties = JsonConvert.DeserializeObject<Dictionary<string, object>>(backupResult);
}
catch (JsonException ex)
{
_logger.LogError($"解析备用API返回数据失败: {ex.Message}");
return null;
}
if (properties == null)
{
_logger.LogInformation($"备用API返回数据为空TaskId: {mJApiTasks.TaskId}");
return null;
}
return properties;
}
catch (Exception ex)
{
// 记录异常日志
_logger.LogError($"Error fetching task: {ex.Message}");
return null;
}
}
private async Task<string?> TryBackupApiAsync(string id, string useToken)
{
string mjAPIBasicUrl = await _tokenService.GetMJAPIBasicUrl();
string backupUrl = $"{mjAPIBasicUrl}/mj/task/{id}/fetch";
const int maxRetries = 3;
const int baseDelayMs = 1000;
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "sk-" + useToken);
client.Timeout = TimeSpan.FromSeconds(30);
for (int attempt = 1; attempt <= maxRetries; attempt++)
{
try
{
var response = await client.GetAsync(backupUrl);
var content = await response.Content.ReadAsStringAsync();
// 判断请求是不是报错
if (!response.IsSuccessStatusCode)
{
_logger.LogWarning("备用API调用返回错误状态码TaskId: {TaskId}, Attempt: {Attempt}, StatusCode: {StatusCode}",
id, attempt, response.StatusCode);
return null;
}
return content;
}
catch (Exception ex) when (IsRetriableException(ex))
{
if (attempt < maxRetries)
{
var delay = baseDelayMs * (int)Math.Pow(2, attempt - 1);
_logger.LogWarning(ex, "备用API调用失败TaskId: {TaskId}, Attempt: {Attempt}, 将在{Delay}ms后重试",
id, attempt, delay);
await Task.Delay(delay);
}
else
{
_logger.LogError(ex, "备用API调用最终失败TaskId: {TaskId}, MaxAttempts: {MaxAttempts}",
id, maxRetries);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "备用API调用发生不可重试异常TaskId: {TaskId}, Attempt: {Attempt}",
id, attempt);
break;
}
}
return null;
}
private static bool IsRetriableException(Exception ex)
{
return ex is HttpRequestException ||
ex is TaskCanceledException ||
ex is SocketException;
}
}
}