101 lines
4.3 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|