- 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
10 KiB
Guida Utente - Schedulazione a Intervalli
🎯 Come Creare una Schedulazione a Intervalli
Opzione 1: Tramite UI (Quando Implementata)
-
Naviga alla sezione Schedulazioni
- Menu → Schedulazioni
-
Clicca "Nuova Schedulazione"
-
Compila il Form
Nome: [Nome descrittivo] Profilo: [Seleziona profilo esistente] Tipo: [Seleziona "A Intervalli"] → Appare configurazione intervalli: Valore Intervallo: [Numero] (es. 5, 10, 30) Unità: [Seleziona] - Secondi - Minuti ← Raccomandato - Ore - Giorni - Settimane - Mesi -
Salva e Attiva
- ✅ Abilita Schedulazione
- Salva
Opzione 2: Tramite Database Diretto
-- Inserisci nuova schedulazione a intervalli
INSERT INTO ProfileSchedules
(
Name,
Description,
ProfileId,
IsEnabled,
ScheduleType,
IntervalValue,
IntervalUnit,
IsActive,
CreatedAt,
CreatedBy
)
VALUES
(
'Sync Clienti Ogni 5 Minuti', -- Nome
'Sincronizzazione automatica clienti', -- Descrizione
1, -- ID del profilo esistente
1, -- Abilitata (1 = true)
'interval', -- Tipo schedulazione
5, -- Valore intervallo
'minutes', -- Unità intervallo
1, -- Attiva (1 = true)
datetime('now'), -- Data creazione
'Admin' -- Creato da
);
Opzione 3: Tramite API/Service (C#)
using CredentialManager.Services;
using CredentialManager.Models;
// Inject IProfileScheduleService
var schedule = new ProfileSchedule
{
Name = "Sync Prodotti Ogni 10 Minuti",
Description = "Sincronizzazione automatica prodotti",
ProfileId = 2, // ID profilo esistente
ScheduleType = "interval",
IntervalValue = 10,
IntervalUnit = "minutes",
IsEnabled = true,
IsActive = true
};
var created = await scheduleService.CreateScheduleAsync(schedule);
Console.WriteLine($"Schedulazione creata con ID: {created.Id}");
Console.WriteLine($"Prossima esecuzione: {created.NextExecutionTime}");
📋 Esempi di Configurazione Comuni
🔵 Sincronizzazione Frequente (Ogni 5 Minuti)
Caso d'uso: Dati che cambiano frequentemente (ordini, inventario real-time)
IntervalValue: 5
IntervalUnit: minutes
Esecuzione: 10:00, 10:05, 10:10, 10:15, 10:20, ...
🟢 Sincronizzazione Oraria (Ogni 1 Ora)
Caso d'uso: Report, statistiche, aggregazioni
IntervalValue: 1
IntervalUnit: hours
Esecuzione: 08:00, 09:00, 10:00, 11:00, 12:00, ...
🟡 Backup Semi-Orario (Ogni 30 Minuti)
Caso d'uso: Backup incrementali, snapshot dati
IntervalValue: 30
IntervalUnit: minutes
Esecuzione: 08:00, 08:30, 09:00, 09:30, 10:00, ...
🔴 Test Rapido (Ogni 30 Secondi)
Caso d'uso: Test, debugging, demo
IntervalValue: 30
IntervalUnit: seconds
Esecuzione: 14:30:00, 14:30:30, 14:31:00, 14:31:30, ...
⚠️ Solo per ambienti di test!
🟣 Sincronizzazione Giornaliera (Ogni 2 Giorni)
Caso d'uso: Archivi, dati storici, backup completi
IntervalValue: 2
IntervalUnit: days
Esecuzione: 01/10 00:00, 03/10 00:00, 05/10 00:00, ...
🟠 Report Settimanale (Ogni 1 Settimana)
Caso d'uso: Report settimanali, consolidamenti
IntervalValue: 1
IntervalUnit: weeks
Esecuzione: 01/10, 08/10, 15/10, 22/10, 29/10, ...
⚫ Archivio Mensile (Ogni 1 Mese)
Caso d'uso: Archiviazioni mensili, report fiscali
IntervalValue: 1
IntervalUnit: months
Esecuzione: 01/10, 01/11, 01/12, 01/01, ...
🔍 Come Verificare una Schedulazione
Query di Controllo
-- Verifica schedulazione creata
SELECT
Id,
Name,
ScheduleType,
IntervalValue,
IntervalUnit,
CONCAT(IntervalValue, ' ', IntervalUnit) as Interval,
IsEnabled,
IsActive,
LastExecutionTime,
NextExecutionTime,
LastExecutionStatus
FROM ProfileSchedules
WHERE ScheduleType = 'interval'
ORDER BY Id DESC;
Verifica Prossima Esecuzione
-- Schedulazioni che verranno eseguite nei prossimi 10 minuti
SELECT
Id,
Name,
NextExecutionTime,
ROUND((JULIANDAY(NextExecutionTime) - JULIANDAY('now')) * 24 * 60, 1) as MinutesToNext
FROM ProfileSchedules
WHERE IsEnabled = 1
AND IsActive = 1
AND NextExecutionTime <= datetime('now', '+10 minutes')
ORDER BY NextExecutionTime;
📊 Monitoraggio Esecuzioni
Storico Ultime Esecuzioni
SELECT
s.Name as ScheduleName,
h.StartTime,
h.EndTime,
ROUND((JULIANDAY(h.EndTime) - JULIANDAY(h.StartTime)) * 24 * 60, 2) as DurationMinutes,
h.Status,
h.RecordsProcessed,
h.Message
FROM ScheduleExecutionHistory h
JOIN ProfileSchedules s ON h.ScheduleId = s.Id
WHERE s.ScheduleType = 'interval'
ORDER BY h.StartTime DESC
LIMIT 20;
Statistiche per Schedulazione
SELECT
s.Name,
s.ScheduleType,
CONCAT(s.IntervalValue, ' ', s.IntervalUnit) as Interval,
COUNT(h.Id) as TotalExecutions,
SUM(CASE WHEN h.Status = 'success' THEN 1 ELSE 0 END) as Successes,
SUM(CASE WHEN h.Status = 'failed' THEN 1 ELSE 0 END) as Failures,
AVG(ROUND((JULIANDAY(h.EndTime) - JULIANDAY(h.StartTime)) * 24 * 60, 2)) as AvgDurationMinutes,
SUM(h.RecordsProcessed) as TotalRecords
FROM ProfileSchedules s
LEFT JOIN ScheduleExecutionHistory h ON s.Id = h.ScheduleId
WHERE s.ScheduleType = 'interval'
AND h.StartTime >= datetime('now', '-24 hours')
GROUP BY s.Id, s.Name, s.ScheduleType, s.IntervalValue, s.IntervalUnit
ORDER BY TotalExecutions DESC;
🛠️ Gestione Schedulazioni
Disabilitare Temporaneamente
-- Disabilita schedulazione (mantiene configurazione)
UPDATE ProfileSchedules
SET IsEnabled = 0
WHERE Id = 1;
Modificare Intervallo
-- Cambia da 5 minuti a 10 minuti
UPDATE ProfileSchedules
SET IntervalValue = 10,
UpdatedAt = datetime('now')
WHERE Id = 1;
Cambiare Unità di Tempo
-- Cambia da minuti a ore
UPDATE ProfileSchedules
SET IntervalValue = 1,
IntervalUnit = 'hours',
UpdatedAt = datetime('now')
WHERE Id = 1;
Riattivare Schedulazione
-- Riattiva schedulazione disabilitata
UPDATE ProfileSchedules
SET IsEnabled = 1,
NextExecutionTime = datetime('now'), -- Esegue subito
UpdatedAt = datetime('now')
WHERE Id = 1;
Eliminare Schedulazione
-- Disattiva definitivamente (soft delete)
UPDATE ProfileSchedules
SET IsActive = 0,
IsEnabled = 0,
UpdatedAt = datetime('now')
WHERE Id = 1;
-- Oppure elimina fisicamente
DELETE FROM ProfileSchedules WHERE Id = 1;
⚠️ Troubleshooting
Schedulazione Non Eseguita
Possibili Cause:
-
Schedulazione disabilitata
SELECT IsEnabled, IsActive FROM ProfileSchedules WHERE Id = X;Soluzione:
UPDATE ProfileSchedules SET IsEnabled = 1 WHERE Id = X; -
NextExecutionTime nel futuro
SELECT NextExecutionTime, datetime('now') as Now FROM ProfileSchedules WHERE Id = X;Soluzione: Attendi orario programmato o aggiorna manualmente
-
Background service non avviato
- Verifica logs applicazione
- Controlla che
ScheduledJobServicesia running
-
Profilo non valido
SELECT p.* FROM ProfileSchedules s LEFT JOIN DataCouplerProfiles p ON s.ProfileId = p.Id WHERE s.Id = X;Soluzione: Verifica che il profilo esista e sia configurato
Schedulazione Eseguita Troppo Frequentemente
Causa: Intervallo troppo breve per la durata dell'esecuzione
Soluzione:
- Aumenta intervallo
- Ottimizza profilo (meno dati, filtri migliori)
- Monitora durata:
SELECT ROUND((JULIANDAY(EndTime) - JULIANDAY(StartTime)) * 24 * 60, 2) as Minutes FROM ScheduleExecutionHistory WHERE ScheduleId = X ORDER BY StartTime DESC LIMIT 10;
Schedulazione Bloccata (Running >1 Ora)
Verifica:
SELECT
Id, Name, LastExecutionStatus, LastExecutionTime,
ROUND((JULIANDAY('now') - JULIANDAY(LastExecutionTime)) * 24, 1) as HoursSince
FROM ProfileSchedules
WHERE LastExecutionStatus = 'running'
AND LastExecutionTime < datetime('now', '-1 hour');
Soluzione:
-- Reset manuale status
UPDATE ProfileSchedules
SET LastExecutionStatus = 'failed',
LastExecutionMessage = 'Timeout manuale - esecuzione bloccata',
NextExecutionTime = datetime('now', '+5 minutes')
WHERE Id = X;
📝 Best Practices
✅ Raccomandazioni
- Intervalli Minimi Produzione: 5-10 minuti
- Test prima di produzione: Prova con intervalli brevi in staging
- Monitora durata: Assicurati che esecuzione < intervallo
- Usa descrizioni chiare: Facilita troubleshooting
- Backup prima di modifiche: Salva configurazioni funzionanti
❌ Da Evitare
- Intervalli <1 minuto in produzione (carico eccessivo)
- Troppi intervalli brevi contemporanei (saturazione risorse)
- Modificare schedulazioni running (rischio inconsistenza)
- Eliminare senza disabilitare prima (perdita log esecuzioni)
🆘 Supporto
Logs Applicazione
Windows Event Log:
Get-EventLog -LogName Application -Source "ScheduledJobService" -Newest 50
File Log (se configurato):
Get-Content logs/datacoupler.log -Tail 100
Query Debug
-- Overview completa schedulazione
SELECT
s.*,
p.Name as ProfileName,
p.SourceType,
p.DestinationType,
(SELECT COUNT(*) FROM ScheduleExecutionHistory WHERE ScheduleId = s.Id) as TotalExecutions,
(SELECT COUNT(*) FROM ScheduleExecutionHistory WHERE ScheduleId = s.Id AND Status = 'success') as SuccessCount,
(SELECT MAX(StartTime) FROM ScheduleExecutionHistory WHERE ScheduleId = s.Id) as LastActualExecution
FROM ProfileSchedules s
LEFT JOIN DataCouplerProfiles p ON s.ProfileId = p.Id
WHERE s.Id = X;
Versione: 2.0
Ultimo Aggiornamento: 2 Ottobre 2025
Documentazione Tecnica: ADVANCED_SCHEDULING_SYSTEM.md