Files
tiku-backend.net/Tiku.Api/Controllers/PlatformOperationsController.cs
xiong c497a3ca8d
Some checks failed
ci / release-gate (push) Has been cancelled
清理代码
2026-08-03 12:31:39 +08:00

136 lines
5.3 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Tiku.Api.Contracts;
using Tiku.Application.Jobs;
using Tiku.Application.PlatformAdmin.Operations;
using Tiku.Application.Security;
using Tiku.Domain.Operations;
namespace Tiku.Api.Controllers;
[ApiController]
[Tags("平台端-运维")]
[Route("api/platform/operations")]
[Authorize(Policy = BackendPermissions.PlatformOperationsView)]
public sealed class PlatformOperationsController(
IBackgroundJobOperations backgroundJobService,
ICurrentUser currentUser,
IPlatformOperationsQueryService operationsQueries) : ControllerBase
{
[HttpGet("health")]
[EndpointSummary("查询受保护的依赖深度健康状态")]
public async Task<ActionResult<object>> Health(CancellationToken cancellationToken)
{
var health = await operationsQueries.GetHealthAsync(cancellationToken);
return Ok(new
{
status = health.Healthy ? "healthy" : "degraded",
database = health.Database,
redis = new { configured = health.RedisConfigured, ready = health.RedisReady },
worker = new { ready = health.WorkerReady, lastHeartbeatAt = health.LastHeartbeatAt },
clamAv = health.ClamAv,
storage = new { provider = health.StorageProvider, configured = health.StorageConfigured },
checkedAt = health.CheckedAt
});
}
[HttpGet("workers")]
[EndpointSummary("查询 Worker 与周期循环状态")]
public async Task<ActionResult<object>> Workers(CancellationToken cancellationToken)
{
var items = await operationsQueries.GetWorkersAsync(cancellationToken);
return Ok(new
{
staleAfterSeconds = 120,
items = items.Select(item => new
{
item.WorkerId,
item.Processor,
item.StartedAt,
item.LastHeartbeatAt,
item.LastIterationStartedAt,
item.LastIterationCompletedAt,
item.LastSucceededAt,
item.LastError,
item.IsRunning,
stale = item.Stale
})
});
}
[HttpGet("job-metrics")]
[EndpointSummary("查询后台任务队列指标")]
public async Task<ActionResult<object>> JobMetrics(CancellationToken cancellationToken)
{
var metrics = await operationsQueries.GetJobMetricsAsync(cancellationToken);
return Ok(new
{
counts = metrics.Counts.Select(item => new { status = item.Status, count = item.Count }),
oldestPendingAt = metrics.OldestPendingAt,
queueAgeSeconds = metrics.QueueAgeSeconds,
expiredLeases = metrics.ExpiredLeases,
checkedAt = metrics.CheckedAt
});
}
[HttpGet("governance-metrics")]
[EndpointSummary("查询审批、配置与通知治理指标")]
public async Task<ActionResult<object>> GovernanceMetrics(CancellationToken cancellationToken)
{
var metrics = await operationsQueries.GetGovernanceMetricsAsync(cancellationToken);
return Ok(new
{
approvals = metrics.Approvals.Select(item => new { status = item.Status, count = item.Count }),
expiredPending = metrics.ExpiredPending,
configurationDrafts = metrics.ConfigurationDrafts,
notifications = metrics.Notifications.Select(item => new { status = item.Status, count = item.Count }),
checkedAt = metrics.CheckedAt
});
}
[HttpGet("jobs")]
[EndpointSummary("查询全平台后台任务")]
public async Task<ActionResult<IReadOnlyCollection<BackgroundJobItem>>> Jobs(
[FromQuery] Guid? tenantId,
[FromQuery] string? jobType,
[FromQuery] BackgroundJobStatus? status,
[FromQuery] int? limit,
CancellationToken cancellationToken)
{
return Ok(await backgroundJobService.ListPlatformAsync(
tenantId, jobType, status, limit ?? 100, cancellationToken));
}
[HttpGet("jobs/{jobId:guid}")]
[EndpointSummary("查询平台后台任务详情")]
public async Task<ActionResult<BackgroundJobItem>> Job(Guid jobId, CancellationToken cancellationToken)
{
var item = await backgroundJobService.GetAsync(jobId, null, cancellationToken);
return item is null ? NotFound() : Ok(item);
}
[HttpPost("jobs/{jobId:guid}/cancel")]
[Authorize(Policy = BackendPermissions.PlatformOperationsManage)]
[EndpointSummary("取消平台后台任务")]
public async Task<ActionResult<BackgroundJobItem>> CancelJob(
Guid jobId,
CancelBackgroundJobDto request,
CancellationToken cancellationToken)
{
return Ok(await backgroundJobService.RequestCancellationAsync(
jobId, null, ResolveUserId(), request.Reason, cancellationToken));
}
[HttpPost("jobs/{jobId:guid}/retry")]
[Authorize(Policy = BackendPermissions.PlatformOperationsManage)]
[EndpointSummary("重试平台后台任务")]
public async Task<ActionResult<BackgroundJobItem>> RetryJob(Guid jobId, CancellationToken cancellationToken)
{
return Ok(await backgroundJobService.RetryAsync(jobId, null, ResolveUserId(), cancellationToken));
}
private Guid ResolveUserId()
{
return currentUser.UserId ?? throw new InvalidOperationException("Current platform user was not resolved.");
}
}