using Microsoft.AspNetCore.Mvc; using TileServer.Application.Sync; using TileServer.Domain.Exceptions; namespace TileServer.Api.Controllers; [ApiController] [Route("api/v1/sync")] public sealed class SyncController(IMapSyncService sync, ILogger logger) : ControllerBase { [HttpGet("status")] [ProducesResponseType(typeof(SyncJobStatus), StatusCodes.Status200OK)] public IActionResult Status() => Ok(sync.GetStatus()); [HttpPost] [ProducesResponseType(StatusCodes.Status202Accepted)] [ProducesResponseType(StatusCodes.Status409Conflict)] public IActionResult RunAll() => Start(() => sync.RunAllAsync(CancellationToken.None), "Synchronization started for all extracts."); [HttpPost("{extractId}")] [ProducesResponseType(StatusCodes.Status202Accepted)] [ProducesResponseType(StatusCodes.Status409Conflict)] public IActionResult RunOne(string extractId) => Start(() => sync.RunOneAsync(extractId, CancellationToken.None), $"Synchronization started for '{extractId}'."); private IActionResult Start(Func work, string message) { if (sync.GetStatus().IsRunning) { return Conflict(new { message = "A synchronization job is already running." }); } _ = RunInBackground(work); return Accepted(new { message }); } private async Task RunInBackground(Func work) { try { await work().ConfigureAwait(false); } catch (ResourceConflictException) { logger.LogInformation("Sync request ignored because another job is running."); } catch (Exception ex) { logger.LogError(ex, "Background synchronization failed."); } } }