d49330e697
Add comprehensive XML documentation (param/returns tags) across 132 source files to improve IntelliSense and API discoverability. Include ConfigManager design documents and implementation plans for phases 1-9.
145 lines
5.4 KiB
C#
145 lines
5.4 KiB
C#
using JdeScoping.Api.Mapping;
|
|
using JdeScoping.Core.ApiContracts;
|
|
using JdeScoping.Core.Models.Pipelines;
|
|
using JdeScoping.Core.Models.Enums;
|
|
using JdeScoping.DataSync.Contracts;
|
|
using JdeScoping.DataSync.Services;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
namespace JdeScoping.Api.Controllers;
|
|
|
|
/// <summary>
|
|
/// API endpoints for pipeline configuration and status.
|
|
/// </summary>
|
|
[Route(ApiRoutes.Pipelines.Base)]
|
|
[Authorize]
|
|
public class PipelineController : ApiControllerBase
|
|
{
|
|
private readonly IEtlPipelineFactory _pipelineFactory;
|
|
private readonly IDataUpdateRepository _dataUpdateRepository;
|
|
private readonly IPipelineMapper _mapper;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="PipelineController"/> class.
|
|
/// </summary>
|
|
/// <param name="pipelineFactory">The ETL pipeline factory.</param>
|
|
/// <param name="dataUpdateRepository">The data update repository.</param>
|
|
/// <param name="mapper">The pipeline mapper.</param>
|
|
public PipelineController(
|
|
IEtlPipelineFactory pipelineFactory,
|
|
IDataUpdateRepository dataUpdateRepository,
|
|
IPipelineMapper mapper)
|
|
{
|
|
_pipelineFactory = pipelineFactory;
|
|
_dataUpdateRepository = dataUpdateRepository;
|
|
_mapper = mapper;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets list of all available pipeline names.
|
|
/// </summary>
|
|
[HttpGet]
|
|
public ActionResult<PipelineListResponse> GetPipelineNames()
|
|
{
|
|
var names = _pipelineFactory.GetAvailableTables()
|
|
.OrderBy(n => n)
|
|
.ToList();
|
|
return Ok(new PipelineListResponse(names));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets configuration for a specific pipeline.
|
|
/// </summary>
|
|
/// <param name="name">The pipeline name.</param>
|
|
[HttpGet(ApiRoutes.Pipelines.ByName)]
|
|
public ActionResult<PipelineConfigDto> GetPipeline(string name)
|
|
{
|
|
var config = _pipelineFactory.GetPipelineConfig(name);
|
|
if (config is null)
|
|
return NotFound();
|
|
|
|
var defaults = _pipelineFactory.GetScheduleDefaults();
|
|
var dto = _mapper.MapToDto(name, config, defaults);
|
|
return Ok(dto);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets schedule status for a pipeline.
|
|
/// </summary>
|
|
/// <param name="name">The pipeline name.</param>
|
|
/// <param name="cancellationToken">The cancellation token.</param>
|
|
[HttpGet(ApiRoutes.Pipelines.Status)]
|
|
public async Task<ActionResult<PipelineStatusResponse>> GetStatus(
|
|
string name,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
var config = _pipelineFactory.GetPipelineConfig(name);
|
|
if (config is null)
|
|
return NotFound();
|
|
|
|
var tableName = config.Destination.Table;
|
|
var lastRuns = await _dataUpdateRepository.GetLastRunsAsync(tableName, cancellationToken);
|
|
var lastSuccessful = await _dataUpdateRepository.GetLastDataUpdatesAsync(cancellationToken);
|
|
var defaults = _pipelineFactory.GetScheduleDefaults();
|
|
|
|
var statuses = new List<PipelineScheduleStatusDto>();
|
|
foreach (var updateType in new[] { UpdateTypes.Mass, UpdateTypes.Daily, UpdateTypes.Hourly })
|
|
{
|
|
var scheduleConfig = _mapper.GetScheduleConfig(config, updateType);
|
|
var interval = _mapper.GetEffectiveInterval(scheduleConfig, defaults, updateType);
|
|
|
|
lastRuns.TryGetValue(updateType, out var lastRun);
|
|
var successKey = $"{tableName}_{(int)updateType}";
|
|
lastSuccessful.TryGetValue(successKey, out var lastSuccess);
|
|
|
|
var nextRequired = lastSuccess?.EndDt?.AddMinutes(interval);
|
|
var isOverdue = DataUpdateRepository.IsOverdue(
|
|
lastSuccess?.EndDt, tableName, updateType, null);
|
|
|
|
statuses.Add(new PipelineScheduleStatusDto(
|
|
updateType,
|
|
lastRun?.StartDt,
|
|
lastRun?.WasSuccessful ?? false,
|
|
lastSuccess?.EndDt,
|
|
nextRequired,
|
|
isOverdue,
|
|
interval));
|
|
}
|
|
|
|
return Ok(new PipelineStatusResponse(statuses));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets recent execution history for a pipeline.
|
|
/// </summary>
|
|
/// <param name="name">The pipeline name.</param>
|
|
/// <param name="count">The maximum number of recent executions to retrieve.</param>
|
|
/// <param name="cancellationToken">The cancellation token.</param>
|
|
[HttpGet(ApiRoutes.Pipelines.Executions)]
|
|
public async Task<ActionResult<PipelineExecutionsResponse>> GetExecutions(
|
|
string name,
|
|
[FromQuery] int count = 30,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var config = _pipelineFactory.GetPipelineConfig(name);
|
|
if (config is null)
|
|
return NotFound();
|
|
|
|
var tableName = config.Destination.Table;
|
|
var updates = await _dataUpdateRepository.GetRecentUpdatesAsync(
|
|
tableName, null, count, cancellationToken);
|
|
|
|
var executions = updates.Select(u => new PipelineExecutionDto(
|
|
u.UpdateType,
|
|
u.StartDt,
|
|
u.EndDt == default ? null : u.EndDt,
|
|
u.EndDt == default ? null : u.EndDt - u.StartDt,
|
|
u.NumberRecords,
|
|
u.WasSuccessful
|
|
)).ToList();
|
|
|
|
return Ok(new PipelineExecutionsResponse(executions));
|
|
}
|
|
}
|