Files
Data-Coupler/SCHEDULING_USER_GUIDE.md
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

10 KiB

Guida Utente - Schedulazione a Intervalli

🎯 Come Creare una Schedulazione a Intervalli

Opzione 1: Tramite UI (Quando Implementata)

  1. Naviga alla sezione Schedulazioni

    • Menu → Schedulazioni
  2. Clicca "Nuova Schedulazione"

  3. 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
    
  4. 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:

  1. Schedulazione disabilitata

    SELECT IsEnabled, IsActive FROM ProfileSchedules WHERE Id = X;
    

    Soluzione: UPDATE ProfileSchedules SET IsEnabled = 1 WHERE Id = X;

  2. NextExecutionTime nel futuro

    SELECT NextExecutionTime, datetime('now') as Now 
    FROM ProfileSchedules WHERE Id = X;
    

    Soluzione: Attendi orario programmato o aggiorna manualmente

  3. Background service non avviato

    • Verifica logs applicazione
    • Controlla che ScheduledJobService sia running
  4. 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:

  1. Aumenta intervallo
  2. Ottimizza profilo (meno dati, filtri migliori)
  3. 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

  1. Intervalli Minimi Produzione: 5-10 minuti
  2. Test prima di produzione: Prova con intervalli brevi in staging
  3. Monitora durata: Assicurati che esecuzione < intervallo
  4. Usa descrizioni chiare: Facilita troubleshooting
  5. Backup prima di modifiche: Salva configurazioni funzionanti

Da Evitare

  1. Intervalli <1 minuto in produzione (carico eccessivo)
  2. Troppi intervalli brevi contemporanei (saturazione risorse)
  3. Modificare schedulazioni running (rischio inconsistenza)
  4. 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