d042863a56
- 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
228 lines
7.5 KiB
C#
228 lines
7.5 KiB
C#
using System.ComponentModel.DataAnnotations;
|
|
using System.ComponentModel.DataAnnotations.Schema;
|
|
|
|
namespace CredentialManager.Models;
|
|
|
|
/// <summary>
|
|
/// Modello per la schedulazione dei profili Data Coupler
|
|
/// </summary>
|
|
public class ProfileSchedule
|
|
{
|
|
[Key]
|
|
public int Id { get; set; }
|
|
|
|
[Required]
|
|
[MaxLength(100)]
|
|
public string Name { get; set; } = string.Empty;
|
|
|
|
[MaxLength(500)]
|
|
public string? Description { get; set; }
|
|
|
|
// Relazione con il profilo
|
|
[Required]
|
|
public int ProfileId { get; set; }
|
|
|
|
[ForeignKey(nameof(ProfileId))]
|
|
public virtual DataCouplerProfile Profile { get; set; } = null!;
|
|
|
|
// Configurazione scheduling
|
|
[Required]
|
|
public bool IsEnabled { get; set; } = true;
|
|
|
|
[Required]
|
|
[MaxLength(20)]
|
|
public string ScheduleType { get; set; } = string.Empty; // "once", "daily", "weekly", "monthly", "interval"
|
|
|
|
public DateTime? ScheduledDateTime { get; set; } // Per schedulazioni "once"
|
|
|
|
[MaxLength(10)]
|
|
public string? DailyTime { get; set; } // Format "HH:mm" per schedulazioni ricorrenti
|
|
|
|
public int? DayOfWeek { get; set; } // 0-6 per schedulazioni settimanali (0=Domenica)
|
|
|
|
public int? DayOfMonth { get; set; } // 1-31 per schedulazioni mensili
|
|
|
|
// Configurazione per schedulazioni a intervalli
|
|
public int? IntervalValue { get; set; } // Valore dell'intervallo (es. 5, 10, 30)
|
|
|
|
[MaxLength(20)]
|
|
public string? IntervalUnit { get; set; } // "seconds", "minutes", "hours", "days", "weeks", "months"
|
|
|
|
// Tracking delle esecuzioni
|
|
public DateTime? LastExecutionTime { get; set; }
|
|
|
|
public DateTime? NextExecutionTime { get; set; }
|
|
|
|
public int ExecutionCount { get; set; } = 0;
|
|
|
|
[MaxLength(20)]
|
|
public string LastExecutionStatus { get; set; } = string.Empty; // "success", "failed", "running"
|
|
|
|
[MaxLength(1000)]
|
|
public string? LastExecutionMessage { get; set; }
|
|
|
|
public int? LastExecutionRecordCount { get; set; }
|
|
|
|
// Configurazione override per database sources
|
|
[MaxLength(100)]
|
|
public string? SourceDatabaseOverride { get; set; }
|
|
|
|
[MaxLength(100)]
|
|
public string? DestinationDatabaseOverride { get; set; }
|
|
|
|
// Metadati
|
|
[MaxLength(100)]
|
|
public string? CreatedBy { get; set; }
|
|
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
|
|
public DateTime? UpdatedAt { get; set; }
|
|
|
|
public bool IsActive { get; set; } = true;
|
|
|
|
// Metodi helper per calcolare la prossima esecuzione
|
|
public DateTime? CalculateNextExecution()
|
|
{
|
|
if (!IsEnabled || !IsActive)
|
|
return null;
|
|
|
|
var now = DateTime.Now;
|
|
|
|
return ScheduleType switch
|
|
{
|
|
"once" => ScheduledDateTime > now ? ScheduledDateTime : null,
|
|
"daily" when !string.IsNullOrEmpty(DailyTime) => CalculateNextDaily(now),
|
|
"weekly" when DayOfWeek.HasValue && !string.IsNullOrEmpty(DailyTime) => CalculateNextWeekly(now),
|
|
"monthly" when DayOfMonth.HasValue && !string.IsNullOrEmpty(DailyTime) => CalculateNextMonthly(now),
|
|
"interval" when IntervalValue.HasValue && !string.IsNullOrEmpty(IntervalUnit) => CalculateNextInterval(now),
|
|
_ => null
|
|
};
|
|
}
|
|
|
|
public DateTime? CalculateNextExecutionFromLast()
|
|
{
|
|
if (!IsEnabled || !IsActive)
|
|
return null;
|
|
|
|
// Per intervalli, calcola dalla ultima esecuzione (o da ora se mai eseguito)
|
|
if (ScheduleType == "interval" && IntervalValue.HasValue && !string.IsNullOrEmpty(IntervalUnit))
|
|
{
|
|
var baseTime = LastExecutionTime ?? DateTime.Now;
|
|
return CalculateNextInterval(baseTime);
|
|
}
|
|
|
|
// Per altri tipi, usa CalculateNextExecution normale
|
|
return CalculateNextExecution();
|
|
}
|
|
|
|
private DateTime CalculateNextDaily(DateTime now)
|
|
{
|
|
var time = TimeSpan.Parse(DailyTime!);
|
|
var today = now.Date.Add(time);
|
|
return today > now ? today : today.AddDays(1);
|
|
}
|
|
|
|
private DateTime CalculateNextWeekly(DateTime now)
|
|
{
|
|
var time = TimeSpan.Parse(DailyTime!);
|
|
var targetDayOfWeek = (DayOfWeek)DayOfWeek!;
|
|
|
|
var daysUntilTarget = ((int)targetDayOfWeek - (int)now.DayOfWeek + 7) % 7;
|
|
if (daysUntilTarget == 0)
|
|
{
|
|
// È oggi, controlla se l'orario è già passato
|
|
var todayAtTime = now.Date.Add(time);
|
|
if (todayAtTime > now)
|
|
return todayAtTime;
|
|
else
|
|
daysUntilTarget = 7; // Prossima settimana
|
|
}
|
|
|
|
return now.Date.AddDays(daysUntilTarget).Add(time);
|
|
}
|
|
|
|
private DateTime CalculateNextMonthly(DateTime now)
|
|
{
|
|
var time = TimeSpan.Parse(DailyTime!);
|
|
var targetDay = DayOfMonth!.Value;
|
|
|
|
var thisMonth = new DateTime(now.Year, now.Month, Math.Min(targetDay, DateTime.DaysInMonth(now.Year, now.Month))).Add(time);
|
|
if (thisMonth > now)
|
|
return thisMonth;
|
|
|
|
// Prossimo mese
|
|
var nextMonth = now.AddMonths(1);
|
|
return new DateTime(nextMonth.Year, nextMonth.Month, Math.Min(targetDay, DateTime.DaysInMonth(nextMonth.Year, nextMonth.Month))).Add(time);
|
|
}
|
|
|
|
private DateTime CalculateNextInterval(DateTime baseTime)
|
|
{
|
|
if (!IntervalValue.HasValue || string.IsNullOrEmpty(IntervalUnit))
|
|
return baseTime;
|
|
|
|
return IntervalUnit.ToLower() switch
|
|
{
|
|
"seconds" => baseTime.AddSeconds(IntervalValue.Value),
|
|
"minutes" => baseTime.AddMinutes(IntervalValue.Value),
|
|
"hours" => baseTime.AddHours(IntervalValue.Value),
|
|
"days" => baseTime.AddDays(IntervalValue.Value),
|
|
"weeks" => baseTime.AddDays(IntervalValue.Value * 7),
|
|
"months" => baseTime.AddMonths(IntervalValue.Value),
|
|
_ => baseTime
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ottiene una descrizione leggibile della schedulazione
|
|
/// </summary>
|
|
public string GetScheduleDescription()
|
|
{
|
|
return ScheduleType switch
|
|
{
|
|
"once" => $"Una volta il {ScheduledDateTime:dd/MM/yyyy HH:mm}",
|
|
"daily" => $"Ogni giorno alle {DailyTime}",
|
|
"weekly" => $"Ogni {GetDayOfWeekName(DayOfWeek)} alle {DailyTime}",
|
|
"monthly" => $"Il giorno {DayOfMonth} di ogni mese alle {DailyTime}",
|
|
"interval" => GetIntervalDescription(),
|
|
_ => "Non configurato"
|
|
};
|
|
}
|
|
|
|
private string GetIntervalDescription()
|
|
{
|
|
if (!IntervalValue.HasValue || string.IsNullOrEmpty(IntervalUnit))
|
|
return "Intervallo non configurato";
|
|
|
|
var unit = IntervalUnit.ToLower() switch
|
|
{
|
|
"seconds" => IntervalValue.Value == 1 ? "secondo" : "secondi",
|
|
"minutes" => IntervalValue.Value == 1 ? "minuto" : "minuti",
|
|
"hours" => IntervalValue.Value == 1 ? "ora" : "ore",
|
|
"days" => IntervalValue.Value == 1 ? "giorno" : "giorni",
|
|
"weeks" => IntervalValue.Value == 1 ? "settimana" : "settimane",
|
|
"months" => IntervalValue.Value == 1 ? "mese" : "mesi",
|
|
_ => IntervalUnit
|
|
};
|
|
|
|
return $"Ogni {IntervalValue} {unit}";
|
|
}
|
|
|
|
private string GetDayOfWeekName(int? dayOfWeek)
|
|
{
|
|
if (!dayOfWeek.HasValue)
|
|
return "sconosciuto";
|
|
|
|
return ((DayOfWeek)dayOfWeek.Value).ToString() switch
|
|
{
|
|
"Monday" => "Lunedì",
|
|
"Tuesday" => "Martedì",
|
|
"Wednesday" => "Mercoledì",
|
|
"Thursday" => "Giovedì",
|
|
"Friday" => "Venerdì",
|
|
"Saturday" => "Sabato",
|
|
"Sunday" => "Domenica",
|
|
_ => dayOfWeek.Value.ToString()
|
|
};
|
|
}
|
|
}
|