Files

101 lines
4.3 KiB
C#

using dy.net.model.dto;
using dy.net.service;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace dy.net.Controllers
{
[Route("api/tasks")]
[ApiController]
[Authorize]
public class TasksController : ControllerBase
{
private readonly VideoTaskService _tasks;
private readonly DouyinQuartzJobService _quartz;
private readonly DouyinVideoService _videos;
public TasksController(VideoTaskService tasks, DouyinQuartzJobService quartz, DouyinVideoService videos)
{
_tasks = tasks;
_quartz = quartz;
_videos = videos;
}
[HttpPost("sync")]
public async Task<IActionResult> StartSync([FromQuery] VideoTypeEnum? videoType = null) => await ExecuteAsync(async () =>
{
var tasks = await _quartz.TriggerVideoJobsNowAsync(videoType);
return ApiResult.Success(new { taskIds = tasks.Select(x => x.Id).ToList(), count = tasks.Count });
});
[HttpGet]
public async Task<IActionResult> List([FromQuery] VideoTaskPageRequest request) =>
ApiResult.Success(await _tasks.GetTasksAsync(request));
[HttpGet("summary")]
public async Task<IActionResult> Summary() => ApiResult.Success(await _tasks.GetSummaryAsync());
[HttpGet("{type}/{id}")]
public async Task<IActionResult> Detail(VideoTaskType type, string id) =>
await ExecuteAsync(async () => ApiResult.Success(await _tasks.GetTaskAsync(type, id)));
[HttpGet("{type}/{id}/items")]
public async Task<IActionResult> Items(VideoTaskType type, string id, [FromQuery] VideoTaskItemPageRequest request) =>
await ExecuteAsync(async () => ApiResult.Success(await _tasks.GetItemsAsync(type, id, request)));
[HttpPost("{type}/{id}/retry-failed")]
public async Task<IActionResult> RetryFailed(VideoTaskType type, string id) =>
await ExecuteAsync(async () =>
{
await _tasks.RetryFailedAsync(type, id);
return ApiResult.Success("重试任务已提交");
});
[HttpPost("{type}/{id}/items/{itemId}/retry")]
public async Task<IActionResult> RetryItem(VideoTaskType type, string id, string itemId) =>
await ExecuteAsync(async () =>
{
await _tasks.RetryItemAsync(type, id, itemId);
return ApiResult.Success("重试任务已提交");
});
[HttpPost("{type}/{id}/items/{itemId}/retry-cleanup")]
public async Task<IActionResult> RetryCleanup(VideoTaskType type, string id, string itemId) =>
await ExecuteAsync(async () =>
{
if (type != VideoTaskType.Sync)
throw new InvalidOperationException("仅普通同步任务支持重试旧本地文件清理。");
var deleted = await _videos.RetryTaskItemLocalCleanupAsync(id, itemId);
return ApiResult.Success(new
{
deletedCount = deleted,
message = deleted > 0 ? $"已清理 {deleted} 个旧本地文件。" : "旧本地文件已不存在或仍被共享引用,清理状态已确认。"
});
});
[HttpPost("{type}/{id}/actions/{action}")]
public async Task<IActionResult> Action(VideoTaskType type, string id, string action, CancellationToken cancellationToken) =>
await ExecuteAsync(async () =>
{
await _tasks.ExecuteTaskActionAsync(type, id, action, cancellationToken);
return ApiResult.Success("操作已提交");
});
[HttpPost("storage-health/probe")]
public async Task<IActionResult> Probe(CancellationToken cancellationToken)
{
var result = await _tasks.ProbeStorageAsync(cancellationToken);
return result.Success ? ApiResult.Success(new { message = result.Message }) : ApiResult.Fail(result.Message);
}
private static async Task<IActionResult> ExecuteAsync(Func<Task<IActionResult>> action)
{
try { return await action(); }
catch (Exception ex) when (ex is InvalidOperationException or KeyNotFoundException)
{
return ApiResult.Fail(ex.Message);
}
}
}
}