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

463 lines
10 KiB
Markdown

# 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
```sql
-- 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#)
```csharp
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)
```sql
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
```sql
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
```sql
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
```sql
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
```sql
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
```sql
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
```sql
IntervalValue: 1
IntervalUnit: months
```
**Esecuzione**: 01/10, 01/11, 01/12, 01/01, ...
---
## 🔍 **Come Verificare una Schedulazione**
### Query di Controllo
```sql
-- 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
```sql
-- 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
```sql
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
```sql
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
```sql
-- Disabilita schedulazione (mantiene configurazione)
UPDATE ProfileSchedules
SET IsEnabled = 0
WHERE Id = 1;
```
### Modificare Intervallo
```sql
-- Cambia da 5 minuti a 10 minuti
UPDATE ProfileSchedules
SET IntervalValue = 10,
UpdatedAt = datetime('now')
WHERE Id = 1;
```
### Cambiare Unità di Tempo
```sql
-- Cambia da minuti a ore
UPDATE ProfileSchedules
SET IntervalValue = 1,
IntervalUnit = 'hours',
UpdatedAt = datetime('now')
WHERE Id = 1;
```
### Riattivare Schedulazione
```sql
-- Riattiva schedulazione disabilitata
UPDATE ProfileSchedules
SET IsEnabled = 1,
NextExecutionTime = datetime('now'), -- Esegue subito
UpdatedAt = datetime('now')
WHERE Id = 1;
```
### Eliminare Schedulazione
```sql
-- 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**
```sql
SELECT IsEnabled, IsActive FROM ProfileSchedules WHERE Id = X;
```
Soluzione: `UPDATE ProfileSchedules SET IsEnabled = 1 WHERE Id = X;`
2. **NextExecutionTime nel futuro**
```sql
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**
```sql
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:
```sql
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**:
```sql
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**:
```sql
-- 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**:
```powershell
Get-EventLog -LogName Application -Source "ScheduledJobService" -Newest 50
```
**File Log** (se configurato):
```powershell
Get-Content logs/datacoupler.log -Tail 100
```
### Query Debug
```sql
-- 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