77 lines
3.1 KiB
C#
77 lines
3.1 KiB
C#
// backend/src/Titulares.Api/Workers/ProcesoScrapingWorker.cs
|
|
|
|
using Microsoft.AspNetCore.SignalR;
|
|
using Titulares.Api.Data;
|
|
using Titulares.Api.Hubs;
|
|
using Titulares.Api.Services;
|
|
using Microsoft.Extensions.Options;
|
|
using Titulares.Api.Models;
|
|
|
|
namespace Titulares.Api.Workers;
|
|
|
|
public class ProcesoScrapingWorker : BackgroundService
|
|
{
|
|
private readonly ILogger<ProcesoScrapingWorker> _logger;
|
|
private readonly IServiceProvider _serviceProvider;
|
|
private readonly IOptionsMonitor<ConfiguracionApp> _configuracion;
|
|
|
|
public ProcesoScrapingWorker(ILogger<ProcesoScrapingWorker> logger, IServiceProvider serviceProvider, IOptionsMonitor<ConfiguracionApp> configuracion)
|
|
{
|
|
_logger = logger;
|
|
_serviceProvider = serviceProvider;
|
|
_configuracion = configuracion;
|
|
}
|
|
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
{
|
|
while (!stoppingToken.IsCancellationRequested)
|
|
{
|
|
var configActual = _configuracion.CurrentValue;
|
|
|
|
_logger.LogInformation("Iniciando ciclo de scraping con cantidad: {cantidad}", configActual.CantidadTitularesAScrapear);
|
|
|
|
try
|
|
{
|
|
// Creamos un 'scope' para obtener instancias 'scoped' de nuestros servicios.
|
|
// Es la práctica correcta en servicios de larga duración.
|
|
using (var scope = _serviceProvider.CreateScope())
|
|
{
|
|
var repositorio = scope.ServiceProvider.GetRequiredService<TitularRepositorio>();
|
|
var scrapingService = scope.ServiceProvider.GetRequiredService<ScrapingService>();
|
|
var hubContext = scope.ServiceProvider.GetRequiredService<IHubContext<TitularesHub>>();
|
|
|
|
// Obtener estos valores desde la configuración
|
|
int cantidadAObtener = configActual.CantidadTitularesAScrapear;
|
|
int limiteTotalEnDb = configActual.LimiteTotalEnDb;
|
|
|
|
// 1. Obtener los últimos titulares de la web
|
|
var articulosScrapeados = await scrapingService.ObtenerUltimosTitulares(cantidadAObtener);
|
|
|
|
if (articulosScrapeados.Any())
|
|
{
|
|
// 2. Sincronizar con la base de datos
|
|
await repositorio.SincronizarDesdeScraping(articulosScrapeados, limiteTotalEnDb);
|
|
_logger.LogInformation("Sincronización con la base de datos completada.");
|
|
|
|
// 3. Notificar a todos los clientes a través de SignalR
|
|
var titularesActualizados = await repositorio.ObtenerTodosAsync();
|
|
await hubContext.Clients.All.SendAsync("TitularesActualizados", titularesActualizados, stoppingToken);
|
|
_logger.LogInformation("Notificación enviada a los clientes.");
|
|
}
|
|
else
|
|
{
|
|
_logger.LogWarning("No se encontraron artículos en el scraping.");
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Ocurrió un error durante el proceso de scraping.");
|
|
}
|
|
|
|
var intervaloEnMinutos = configActual.IntervaloMinutos;
|
|
_logger.LogInformation("Proceso en espera por {minutos} minutos.", intervaloEnMinutos);
|
|
await Task.Delay(TimeSpan.FromMinutes(intervaloEnMinutos), stoppingToken);
|
|
}
|
|
}
|
|
} |