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
463 lines
10 KiB
Markdown
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
|