Files
Data-Coupler/Data_Coupler/Extensions/DataCoupler/RESTMethod.cs
T
Alessio d042863a56 feat: Implementazione completa sistema schedulazione con intervalli personalizzati
- Aggiunto supporto schedulazione con intervalli flessibili (secondi/minuti/ore/giorni/settimane/mesi)
- Esteso modello ProfileSchedule con campi IntervalValue e IntervalUnit
- Ottimizzato ScheduledJobService per controlli ogni 30s con esecuzione parallela
- Implementata interfaccia UI completa con anteprima real-time in italiano
- Aggiunta migrazione database AddIntervalSchedulingFields
- Implementati metodi calcolo NextExecutionTime per intervalli
- Aggiunta gestione tracking anti-duplicati e cleanup automatico
- Creata documentazione completa (6 file, 2500+ righe)

Modifiche tecniche:
- ProfileSchedule.cs: Nuovi campi e metodi CalculateNextInterval/GetScheduleDescription
- ScheduledJobService.cs: Ridotto check interval a 30s, aggiunto parallel processing
- ProfileScheduleService.cs: Supporto calcolo intervalli in UpdateNextExecutionTimeAsync
- Scheduling.razor: Aggiunta sezione UI per configurazione intervalli
- Scheduling.razor.cs: Implementato GetIntervalPreview() e gestione stato campi
2025-10-02 01:12:39 +02:00

231 lines
7.7 KiB
C#

using System;
using System.ComponentModel;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.JSInterop;
using Microsoft.Extensions.Logging;
using CredentialManager.Models;
using DataConnection.REST.Interfaces;
using DataConnection.REST.Models;
using DataConnection.CredentialManagement.Interfaces;
using DataConnection.Interfaces;
using Data_Coupler.Services;
using Data_Coupler.Models;
namespace Data_Coupler.Pages;
public partial class DataCoupler : ComponentBase
{
// ===== PROPRIETÀ REST =====
// Credenziali REST
protected List<RestApiCredential> restApiCredentials = new();
protected string selectedRestCredential = "";
// Stato connessioni REST
protected bool isConnectingRest = false;
protected bool isRestConnected = false;
protected string restErrorMessage = "";
// REST discovery
protected List<RestEntitySummary> restEntities = new();
protected RestEntitySummary? selectedRestEntity = null;
protected RestEntityInfo? restEntityDetails = null;
protected string restSearchTerm = "";
// Proprietà di mapping REST
protected string selectedRestProperty = "";
// Servizi REST
protected IRestMetadataDiscovery? currentRestDiscovery = null;
protected IRestServiceClient? currentRestClient = null;
// ===== METODI REST =====
/// <summary>
/// Carica le credenziali REST API
/// </summary>
protected async Task LoadRestCredentials()
{
try
{
restApiCredentials = await CredentialService.GetAllRestApiCredentialsAsync();
}
catch (Exception ex)
{
Logger.LogError(ex, "Errore nel caricamento delle credenziali REST");
throw;
}
}
/// <summary>
/// Gestisce il cambio di credenziale REST
/// </summary>
private void OnRestCredentialChanged(ChangeEventArgs e)
{
var newCredential = e.Value?.ToString() ?? "";
// Clear the cache if we're switching to a different credential
if (!string.IsNullOrEmpty(selectedRestCredential) && selectedRestCredential != newCredential)
{
ConnectionFactory.ClearRestClientCache(selectedRestCredential);
Logger.LogInformation("Cleared REST client cache for credential: {CredentialName}", selectedRestCredential);
}
selectedRestCredential = newCredential;
ResetRestState();
}
/// <summary>
/// Resetta lo stato REST
/// </summary>
protected void ResetRestState()
{
isRestConnected = false;
restEntities.Clear();
selectedRestEntity = null;
restEntityDetails = null;
restSearchTerm = "";
restErrorMessage = "";
currentRestDiscovery = null;
currentRestClient = null;
// Clear mappings when resetting REST state - handled by main class
// ClearAllMappings();
}
/// <summary>
/// Connette al servizio REST API
/// </summary>
protected async Task ConnectToRestApi()
{
if (string.IsNullOrEmpty(selectedRestCredential))
return;
isConnectingRest = true;
restErrorMessage = "";
try
{
// Trova la credenziale
var credential = restApiCredentials.FirstOrDefault(c => c.Name == selectedRestCredential);
if (credential == null)
{
restErrorMessage = "Credenziale REST API non trovata";
return;
}
// Test della connessione
var (success, message) = await CredentialService.TestRestApiConnectionAsync(credential.Name);
if (!success)
{
restErrorMessage = $"Connessione fallita: {message}";
return;
}
// Crea i client REST usando il factory con le credenziali complete
currentRestClient = await ConnectionFactory.CreateRestServiceClientAsync(selectedRestCredential);
currentRestDiscovery = await ConnectionFactory.CreateRestMetadataDiscoveryAsync(selectedRestCredential);
Logger.LogInformation("Iniziando autenticazione per il servizio REST {ServiceType} con credenziale: {CredentialName}", credential.ServiceType, selectedRestCredential);
// Autenticazione prima del discovery
var authResult = await currentRestClient.AuthenticateAsync();
if (!authResult)
{
Logger.LogWarning("Autenticazione fallita per il servizio REST {ServiceType}", credential.ServiceType);
restErrorMessage = "Autenticazione fallita per il servizio REST";
return;
}
Logger.LogInformation("Autenticazione completata con successo per il servizio REST {ServiceType}", credential.ServiceType);
// Discovery delle entità disponibili usando il metodo batch ottimizzato
Logger.LogInformation("Iniziando discovery batch delle entità REST...");
restEntities = await currentRestDiscovery.DiscoverEntitySummariesAsync();
isRestConnected = true;
Logger.LogInformation("Discovery batch completato: trovate {EntityCount} entità REST", restEntities.Count);
}
catch (Exception ex)
{
Logger.LogError(ex, "Errore nella connessione al servizio REST {ServiceType}", selectedRestCredential);
restErrorMessage = $"Errore nella connessione: {ex.Message}";
}
finally
{
isConnectingRest = false;
StateHasChanged();
}
}
/// <summary>
/// Seleziona un'entità REST
/// </summary>
protected async Task SelectRestEntity(RestEntitySummary entity)
{
selectedRestEntity = entity;
// Clear mappings when changing entity - handled by main class
// ClearAllMappings();
try
{
if (currentRestDiscovery != null)
{
// Discovery dei dettagli dell'entità
restEntityDetails = await currentRestDiscovery.DiscoverEntityDetailsAsync(entity.Name);
}
else
{
restErrorMessage = "Servizio di discovery REST non disponibile";
return;
}
}
catch (Exception ex)
{
Logger.LogError(ex, "Errore nel caricamento dettagli entità {EntityName}", entity.Name);
restErrorMessage = $"Errore nel caricamento dettagli entità: {ex.Message}";
}
}
/// <summary>
/// Filtra le entità REST in base al termine di ricerca
/// </summary>
private IEnumerable<RestEntitySummary> GetFilteredRestEntities()
{
if (string.IsNullOrEmpty(restSearchTerm))
return restEntities;
return restEntities.Where(entity =>
entity.Name.Contains(restSearchTerm, StringComparison.OrdinalIgnoreCase) ||
(!string.IsNullOrEmpty(entity.Label) && entity.Label.Contains(restSearchTerm, StringComparison.OrdinalIgnoreCase)));
}
/// <summary>
/// Applica il filtro alle entità REST
/// </summary>
private async Task FilterRestEntities(ChangeEventArgs e)
{
restSearchTerm = e.Value?.ToString() ?? "";
await InvokeAsync(StateHasChanged);
}
/// <summary>
/// Pulisce la ricerca delle entità REST
/// </summary>
private async Task ClearRestSearch()
{
restSearchTerm = "";
await InvokeAsync(StateHasChanged);
}
/// <summary>
/// Seleziona una proprietà REST per il mapping
/// </summary>
protected void SelectRestProperty(string propertyName)
{
selectedRestProperty = propertyName;
}
}