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
This commit is contained in:
@@ -0,0 +1,666 @@
|
||||
# Sistema di Schedulazione Avanzata - Data Coupler
|
||||
|
||||
## 📋 Panoramica
|
||||
|
||||
**Data**: 2 Ottobre 2025
|
||||
**Feature**: Sistema di schedulazione completo con supporto per intervalli personalizzati
|
||||
**Versione**: 2.0
|
||||
|
||||
---
|
||||
|
||||
## 🚀 **Funzionalità Implementate**
|
||||
|
||||
### Tipi di Schedulazione Supportati
|
||||
|
||||
1. **✅ Una Volta (Once)**
|
||||
- Esecuzione singola a una data/ora specifica
|
||||
- Ideale per migrazioni one-time o test
|
||||
|
||||
2. **✅ Giornaliera (Daily)**
|
||||
- Esecuzione ogni giorno a un orario specifico
|
||||
- Esempio: Ogni giorno alle 02:00
|
||||
|
||||
3. **✅ Settimanale (Weekly)**
|
||||
- Esecuzione ogni settimana in un giorno specifico
|
||||
- Esempio: Ogni Lunedì alle 08:00
|
||||
|
||||
4. **✅ Mensile (Monthly)**
|
||||
- Esecuzione ogni mese in un giorno specifico
|
||||
- Esempio: Il giorno 1 di ogni mese alle 00:00
|
||||
|
||||
5. **🆕 A Intervalli (Interval)** - NUOVA!
|
||||
- Esecuzione ricorrente ogni N unità di tempo
|
||||
- Supporta:
|
||||
- **Secondi**: Ogni N secondi (utile per test/demo)
|
||||
- **Minuti**: Ogni N minuti (es. ogni 5, 10, 15, 30 minuti)
|
||||
- **Ore**: Ogni N ore (es. ogni 1, 2, 4, 6, 12 ore)
|
||||
- **Giorni**: Ogni N giorni (es. ogni 2, 3, 7 giorni)
|
||||
- **Settimane**: Ogni N settimane (es. ogni 2, 4 settimane)
|
||||
- **Mesi**: Ogni N mesi (es. ogni 2, 3, 6 mesi)
|
||||
|
||||
---
|
||||
|
||||
## 🔧 **Modifiche Implementate**
|
||||
|
||||
### 1. Modello Dati - ProfileSchedule
|
||||
|
||||
**File**: `CredentialManager/Models/ProfileSchedule.cs`
|
||||
|
||||
#### Nuovi Campi
|
||||
|
||||
```csharp
|
||||
// Configurazione per schedulazioni a intervalli
|
||||
public int? IntervalValue { get; set; } // Valore dell'intervallo (es. 5, 10, 30)
|
||||
public string? IntervalUnit { get; set; } // "seconds", "minutes", "hours", "days", "weeks", "months"
|
||||
```
|
||||
|
||||
#### Nuovi Metodi
|
||||
|
||||
```csharp
|
||||
/// <summary>
|
||||
/// Calcola la prossima esecuzione basandosi sulla data/ora base fornita
|
||||
/// Per intervalli, aggiunge l'intervallo alla data base
|
||||
/// </summary>
|
||||
public DateTime? CalculateNextExecutionFromLast()
|
||||
|
||||
/// <summary>
|
||||
/// Calcola la prossima esecuzione aggiungendo l'intervallo alla data base
|
||||
/// </summary>
|
||||
private DateTime CalculateNextInterval(DateTime baseTime)
|
||||
|
||||
/// <summary>
|
||||
/// Ottiene una descrizione leggibile della schedulazione
|
||||
/// </summary>
|
||||
public string GetScheduleDescription()
|
||||
```
|
||||
|
||||
#### Esempi di Utilizzo
|
||||
|
||||
```csharp
|
||||
// Ogni 5 minuti
|
||||
var schedule = new ProfileSchedule
|
||||
{
|
||||
ScheduleType = "interval",
|
||||
IntervalValue = 5,
|
||||
IntervalUnit = "minutes"
|
||||
};
|
||||
// Descrizione: "Ogni 5 minuti"
|
||||
|
||||
// Ogni 2 ore
|
||||
var schedule = new ProfileSchedule
|
||||
{
|
||||
ScheduleType = "interval",
|
||||
IntervalValue = 2,
|
||||
IntervalUnit = "hours"
|
||||
};
|
||||
// Descrizione: "Ogni 2 ore"
|
||||
|
||||
// Ogni 30 secondi (utile per test)
|
||||
var schedule = new ProfileSchedule
|
||||
{
|
||||
ScheduleType = "interval",
|
||||
IntervalValue = 30,
|
||||
IntervalUnit = "seconds"
|
||||
};
|
||||
// Descrizione: "Ogni 30 secondi"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Background Service - ScheduledJobService
|
||||
|
||||
**File**: `Data_Coupler/BackgroundServices/ScheduledJobService.cs`
|
||||
|
||||
#### Miglioramenti Principali
|
||||
|
||||
##### ✅ Intervallo di Controllo Ridotto
|
||||
|
||||
```csharp
|
||||
// PRIMA: TimeSpan.FromMinutes(1) // Controllo ogni minuto
|
||||
// DOPO: TimeSpan.FromSeconds(30) // Controllo ogni 30 secondi
|
||||
```
|
||||
|
||||
**Motivazione**: Supportare schedulazioni a intervalli brevi (secondi/minuti) richiede controlli più frequenti.
|
||||
|
||||
##### ✅ Esecuzione Parallela
|
||||
|
||||
```csharp
|
||||
// Esegue più schedulazioni contemporaneamente
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await ExecuteScheduleAsync(schedule, cancellationToken);
|
||||
}, cancellationToken);
|
||||
```
|
||||
|
||||
**Benefici**:
|
||||
- Più schedulazioni possono essere eseguite simultaneamente
|
||||
- Non blocca altre schedulazioni se una è lenta
|
||||
- Migliora throughput complessivo
|
||||
|
||||
##### ✅ Tracking Esecuzioni
|
||||
|
||||
```csharp
|
||||
private readonly Dictionary<int, DateTime> _runningSchedules = new();
|
||||
|
||||
private bool IsScheduleRunning(int scheduleId)
|
||||
private void MarkScheduleAsRunning(int scheduleId)
|
||||
private void MarkScheduleAsCompleted(int scheduleId)
|
||||
private void CleanupRunningSchedules() // Rimuove schedulazioni bloccate dopo 1 ora
|
||||
```
|
||||
|
||||
**Protezioni**:
|
||||
- Previene esecuzioni duplicate della stessa schedulazione
|
||||
- Rileva e pulisce schedulazioni bloccate (timeout 1 ora)
|
||||
- Thread-safe con lock
|
||||
|
||||
##### ✅ Tolleranza Temporale Adattiva
|
||||
|
||||
```csharp
|
||||
var tolerance = schedule.ScheduleType == "interval"
|
||||
? TimeSpan.FromSeconds(30) // 30 secondi per intervalli
|
||||
: TimeSpan.FromMinutes(1); // 1 minuto per altre schedulazioni
|
||||
```
|
||||
|
||||
**Motivazione**: Schedulazioni a intervalli necessitano tolleranza più stretta per precisione.
|
||||
|
||||
---
|
||||
|
||||
### 3. Service Layer - ProfileScheduleService
|
||||
|
||||
**File**: `CredentialManager/Services/ProfileScheduleService.cs`
|
||||
|
||||
#### Aggiornamenti
|
||||
|
||||
```csharp
|
||||
public async Task UpdateNextExecutionTimeAsync(int scheduleId)
|
||||
{
|
||||
var schedule = await _context.ProfileSchedules.FindAsync(scheduleId);
|
||||
|
||||
// Per schedulazioni a intervallo, calcola dalla ultima esecuzione
|
||||
if (schedule.ScheduleType == "interval")
|
||||
{
|
||||
schedule.NextExecutionTime = schedule.CalculateNextExecutionFromLast();
|
||||
}
|
||||
else
|
||||
{
|
||||
schedule.NextExecutionTime = schedule.CalculateNextExecution();
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
```
|
||||
|
||||
**Differenza Chiave**:
|
||||
- **Intervalli**: Calcola da `LastExecutionTime` (tempo trascorso + intervallo)
|
||||
- **Altri tipi**: Calcola da `Now` (prossimo orario programmato)
|
||||
|
||||
---
|
||||
|
||||
### 4. Database Migration
|
||||
|
||||
**File**: `CredentialManager/Migrations/[timestamp]_AddIntervalSchedulingFields.cs`
|
||||
|
||||
#### Modifiche Schema
|
||||
|
||||
```sql
|
||||
ALTER TABLE ProfileSchedules
|
||||
ADD IntervalValue INT NULL;
|
||||
|
||||
ALTER TABLE ProfileSchedules
|
||||
ADD IntervalUnit NVARCHAR(20) NULL;
|
||||
```
|
||||
|
||||
**Compatibilità**: Campi nullable, schedulazioni esistenti non impattate.
|
||||
|
||||
---
|
||||
|
||||
## 📊 **Esempi Pratici di Utilizzo**
|
||||
|
||||
### Caso 1: Sincronizzazione Frequente (Ogni 5 Minuti)
|
||||
|
||||
```json
|
||||
{
|
||||
"Name": "Sincronizzazione Clienti Frequente",
|
||||
"ProfileId": 1,
|
||||
"ScheduleType": "interval",
|
||||
"IntervalValue": 5,
|
||||
"IntervalUnit": "minutes",
|
||||
"IsEnabled": true
|
||||
}
|
||||
```
|
||||
|
||||
**Esecuzione**:
|
||||
```
|
||||
10:00:00 - Prima esecuzione
|
||||
10:05:00 - Seconda esecuzione (+5 minuti)
|
||||
10:10:00 - Terza esecuzione (+5 minuti)
|
||||
10:15:00 - Quarta esecuzione (+5 minuti)
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Caso 2: Backup Orario
|
||||
|
||||
```json
|
||||
{
|
||||
"Name": "Backup Orario Prodotti",
|
||||
"ProfileId": 2,
|
||||
"ScheduleType": "interval",
|
||||
"IntervalValue": 1,
|
||||
"IntervalUnit": "hours",
|
||||
"IsEnabled": true
|
||||
}
|
||||
```
|
||||
|
||||
**Esecuzione**:
|
||||
```
|
||||
08:00:00 - Prima esecuzione
|
||||
09:00:00 - Seconda esecuzione (+1 ora)
|
||||
10:00:00 - Terza esecuzione (+1 ora)
|
||||
11:00:00 - Quarta esecuzione (+1 ora)
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Caso 3: Test Rapido (Ogni 30 Secondi)
|
||||
|
||||
```json
|
||||
{
|
||||
"Name": "Test Sync Veloce",
|
||||
"ProfileId": 3,
|
||||
"ScheduleType": "interval",
|
||||
"IntervalValue": 30,
|
||||
"IntervalUnit": "seconds",
|
||||
"IsEnabled": true
|
||||
}
|
||||
```
|
||||
|
||||
**Esecuzione**:
|
||||
```
|
||||
14:30:00 - Prima esecuzione
|
||||
14:30:30 - Seconda esecuzione (+30 secondi)
|
||||
14:31:00 - Terza esecuzione (+30 secondi)
|
||||
14:31:30 - Quarta esecuzione (+30 secondi)
|
||||
...
|
||||
```
|
||||
|
||||
⚠️ **Attenzione**: Intervalli molto brevi (<1 minuto) dovrebbero essere usati solo per test o scenari specifici.
|
||||
|
||||
---
|
||||
|
||||
### Caso 4: Sincronizzazione Bi-Settimanale
|
||||
|
||||
```json
|
||||
{
|
||||
"Name": "Sync Archivio Bi-Settimanale",
|
||||
"ProfileId": 4,
|
||||
"ScheduleType": "interval",
|
||||
"IntervalValue": 2,
|
||||
"IntervalUnit": "weeks",
|
||||
"IsEnabled": true
|
||||
}
|
||||
```
|
||||
|
||||
**Esecuzione**:
|
||||
```
|
||||
01/10/2025 00:00 - Prima esecuzione
|
||||
15/10/2025 00:00 - Seconda esecuzione (+2 settimane)
|
||||
29/10/2025 00:00 - Terza esecuzione (+2 settimane)
|
||||
12/11/2025 00:00 - Quarta esecuzione (+2 settimane)
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 **Logica di Schedulazione**
|
||||
|
||||
### Calcolo Prossima Esecuzione
|
||||
|
||||
#### Per Schedulazioni a Intervallo
|
||||
|
||||
```
|
||||
NextExecutionTime = LastExecutionTime + Intervallo
|
||||
|
||||
Esempio:
|
||||
- LastExecutionTime = 14:30:00
|
||||
- IntervalValue = 15
|
||||
- IntervalUnit = "minutes"
|
||||
- NextExecutionTime = 14:30:00 + 15 minuti = 14:45:00
|
||||
```
|
||||
|
||||
**Comportamento Primo Avvio**:
|
||||
```
|
||||
Se LastExecutionTime è NULL (mai eseguita):
|
||||
NextExecutionTime = DateTime.Now + Intervallo
|
||||
```
|
||||
|
||||
#### Per Altre Schedulazioni
|
||||
|
||||
```
|
||||
NextExecutionTime = Prossimo Orario Programmato
|
||||
|
||||
Esempio Daily:
|
||||
- DailyTime = "02:00"
|
||||
- Now = 14:30
|
||||
- NextExecutionTime = Domani alle 02:00
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Controllo Esecuzioni
|
||||
|
||||
```
|
||||
Ogni 30 secondi il ScheduledJobService:
|
||||
1. Recupera tutte le schedulazioni attive
|
||||
2. Filtra quelle con NextExecutionTime <= Now + Tolleranza
|
||||
3. Verifica che non siano già in esecuzione
|
||||
4. Le esegue in parallelo (Task.Run)
|
||||
5. Aggiorna NextExecutionTime dopo completamento
|
||||
```
|
||||
|
||||
**Tolleranza Temporale**:
|
||||
- Intervalli: ±30 secondi
|
||||
- Altri tipi: ±1 minuto
|
||||
|
||||
---
|
||||
|
||||
## ⚡ **Performance e Ottimizzazioni**
|
||||
|
||||
### Esecuzione Parallela
|
||||
|
||||
```csharp
|
||||
// Più schedulazioni possono essere eseguite contemporaneamente
|
||||
foreach (var schedule in pendingSchedules)
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await ExecuteScheduleAsync(schedule, cancellationToken);
|
||||
}, cancellationToken);
|
||||
}
|
||||
```
|
||||
|
||||
**Vantaggi**:
|
||||
- ✅ Throughput migliorato
|
||||
- ✅ Schedulazioni lente non bloccano altre
|
||||
- ✅ Migliore utilizzo risorse
|
||||
|
||||
**Protezioni**:
|
||||
- ✅ Tracking per evitare duplicati
|
||||
- ✅ Timeout dopo 1 ora (pulizia automatica)
|
||||
- ✅ Gestione errori isolata per schedulazione
|
||||
|
||||
---
|
||||
|
||||
### Controlli Più Frequenti
|
||||
|
||||
```csharp
|
||||
// Controllo ogni 30 secondi invece di 1 minuto
|
||||
private TimeSpan _checkInterval = TimeSpan.FromSeconds(30);
|
||||
```
|
||||
|
||||
**Motivazione**:
|
||||
- Supportare intervalli brevi (es. ogni 30 secondi, ogni minuto)
|
||||
- Maggiore precisione temporale
|
||||
- Impatto trascurabile su performance (query leggere)
|
||||
|
||||
---
|
||||
|
||||
## 🔍 **Monitoraggio e Debug**
|
||||
|
||||
### Logging Dettagliato
|
||||
|
||||
```csharp
|
||||
// Ogni controllo (LogTrace - solo se abilitato)
|
||||
_logger.LogTrace("Nessuna schedulazione in sospeso trovata");
|
||||
|
||||
// Esecuzioni trovate (LogInformation)
|
||||
_logger.LogInformation("Trovate {Count} schedulazioni da eseguire", count);
|
||||
|
||||
// Schedulazioni già running (LogDebug)
|
||||
_logger.LogDebug("Schedulazione {ScheduleId} già in esecuzione, salto", id);
|
||||
|
||||
// Aggiornamento prossima esecuzione (LogDebug)
|
||||
_logger.LogDebug("Prossima esecuzione aggiornata: {NextExecution} (tipo: {Type})",
|
||||
nextTime, scheduleType);
|
||||
|
||||
// Completamento con successo (LogInformation)
|
||||
_logger.LogInformation("Schedulazione {ScheduleId} eseguita: {Records} record, {Duration}s",
|
||||
id, records, duration);
|
||||
|
||||
// Errori (LogError)
|
||||
_logger.LogError(ex, "Errore durante l'esecuzione schedulazione {ScheduleId}", id);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Query Monitoraggio
|
||||
|
||||
```sql
|
||||
-- Schedulazioni attive per tipo
|
||||
SELECT
|
||||
ScheduleType,
|
||||
COUNT(*) as Total,
|
||||
SUM(CASE WHEN IsEnabled = 1 THEN 1 ELSE 0 END) as Enabled
|
||||
FROM ProfileSchedules
|
||||
WHERE IsActive = 1
|
||||
GROUP BY ScheduleType;
|
||||
|
||||
-- Schedulazioni a intervallo con dettagli
|
||||
SELECT
|
||||
Id,
|
||||
Name,
|
||||
IntervalValue,
|
||||
IntervalUnit,
|
||||
CONCAT(IntervalValue, ' ', IntervalUnit) as Interval,
|
||||
LastExecutionTime,
|
||||
NextExecutionTime,
|
||||
LastExecutionStatus
|
||||
FROM ProfileSchedules
|
||||
WHERE ScheduleType = 'interval'
|
||||
AND IsEnabled = 1
|
||||
ORDER BY NextExecutionTime;
|
||||
|
||||
-- Statistiche esecuzioni ultima ora
|
||||
SELECT
|
||||
s.Name,
|
||||
s.ScheduleType,
|
||||
COUNT(h.Id) as ExecutionCount,
|
||||
AVG(DATEDIFF(SECOND, h.StartTime, h.EndTime)) as AvgDurationSeconds,
|
||||
SUM(h.RecordsProcessed) as TotalRecords
|
||||
FROM ProfileSchedules s
|
||||
LEFT JOIN ScheduleExecutionHistory h ON s.Id = h.ScheduleId
|
||||
WHERE h.StartTime >= DATEADD(HOUR, -1, GETDATE())
|
||||
GROUP BY s.Id, s.Name, s.ScheduleType
|
||||
ORDER BY ExecutionCount DESC;
|
||||
|
||||
-- Schedulazioni bloccate (running da >1 ora)
|
||||
SELECT
|
||||
Id,
|
||||
Name,
|
||||
LastExecutionStatus,
|
||||
LastExecutionTime,
|
||||
DATEDIFF(MINUTE, LastExecutionTime, GETDATE()) as MinutesSinceExecution
|
||||
FROM ProfileSchedules
|
||||
WHERE LastExecutionStatus = 'running'
|
||||
AND LastExecutionTime < DATEADD(HOUR, -1, GETDATE());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ **Limitazioni e Considerazioni**
|
||||
|
||||
### Intervalli Molto Brevi (<1 Minuto)
|
||||
|
||||
**⚠️ Attenzione**:
|
||||
- Intervalli di pochi secondi generano molte esecuzioni
|
||||
- Aumentano carico database e API
|
||||
- Dovrebbero essere usati solo per:
|
||||
- Test e demo
|
||||
- Scenari critici real-time
|
||||
- Ambienti con risorse dedicate
|
||||
|
||||
**Raccomandazioni**:
|
||||
- **Produzione**: Minimo 5-10 minuti
|
||||
- **Test**: 30 secondi - 2 minuti OK
|
||||
- **Dev**: Qualsiasi intervallo
|
||||
|
||||
---
|
||||
|
||||
### Esecuzioni Parallele
|
||||
|
||||
**Comportamento**:
|
||||
- Più schedulazioni possono essere eseguite contemporaneamente
|
||||
- Stessa schedulazione NON può essere eseguita due volte in parallelo
|
||||
|
||||
**Implicazioni**:
|
||||
- Se una schedulazione impiega più tempo del suo intervallo, alcune esecuzioni verranno saltate
|
||||
- Esempio: Intervallo 5 minuti, ma esecuzione richiede 7 minuti → Una esecuzione verrà saltata
|
||||
|
||||
**Soluzione**:
|
||||
- Aumentare l'intervallo
|
||||
- Ottimizzare il profilo di trasferimento
|
||||
- Monitorare durata esecuzioni
|
||||
|
||||
---
|
||||
|
||||
### Drift Temporale
|
||||
|
||||
**Per Intervalli Lunghi** (giorni/settimane/mesi):
|
||||
```
|
||||
Esempio: Ogni 2 settimane
|
||||
- Prima esecuzione: 01/10/2025 14:30:00
|
||||
- Seconda esecuzione: 15/10/2025 14:30:00 (esatta)
|
||||
- Terza esecuzione: 29/10/2025 14:30:00 (esatta)
|
||||
|
||||
Se una esecuzione ritarda:
|
||||
- Seconda esecuzione: 15/10/2025 14:35:00 (ritardo 5 minuti)
|
||||
- Terza esecuzione: 29/10/2025 14:35:00 (drift propagato)
|
||||
```
|
||||
|
||||
**Mitigazione**:
|
||||
- Tolleranza di ±30 secondi assorbe piccole variazioni
|
||||
- Per intervalli lunghi, il drift è trascurabile (secondi su giorni)
|
||||
- Considerare schedulazioni daily/weekly/monthly se serve orario esatto
|
||||
|
||||
---
|
||||
|
||||
## 🧪 **Testing**
|
||||
|
||||
### Test Schedulazione a 30 Secondi
|
||||
|
||||
```csharp
|
||||
var schedule = new ProfileSchedule
|
||||
{
|
||||
Name = "Test Rapid Sync",
|
||||
ProfileId = 1,
|
||||
ScheduleType = "interval",
|
||||
IntervalValue = 30,
|
||||
IntervalUnit = "seconds",
|
||||
IsEnabled = true,
|
||||
IsActive = true
|
||||
};
|
||||
|
||||
await scheduleService.CreateScheduleAsync(schedule);
|
||||
|
||||
// Osserva i log ogni 30 secondi:
|
||||
// 14:30:00 - Esecuzione 1
|
||||
// 14:30:30 - Esecuzione 2
|
||||
// 14:31:00 - Esecuzione 3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Test Schedulazione a 5 Minuti
|
||||
|
||||
```csharp
|
||||
var schedule = new ProfileSchedule
|
||||
{
|
||||
Name = "Test 5 Minutes Sync",
|
||||
ProfileId = 2,
|
||||
ScheduleType = "interval",
|
||||
IntervalValue = 5,
|
||||
IntervalUnit = "minutes",
|
||||
IsEnabled = true,
|
||||
IsActive = true
|
||||
};
|
||||
|
||||
await scheduleService.CreateScheduleAsync(schedule);
|
||||
|
||||
// Osserva i log ogni 5 minuti:
|
||||
// 10:00 - Esecuzione 1
|
||||
// 10:05 - Esecuzione 2
|
||||
// 10:10 - Esecuzione 3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 **Checklist Deployment**
|
||||
|
||||
### Pre-Deploy
|
||||
|
||||
- [x] Migration database creata
|
||||
- [x] Codice compilato senza errori
|
||||
- [x] Logging configurato correttamente
|
||||
- [ ] Backup database production
|
||||
- [ ] Test in ambiente staging
|
||||
|
||||
### Deploy
|
||||
|
||||
1. **Stop servizio esistente**
|
||||
```powershell
|
||||
Stop-Service -Name "DataCouplerService"
|
||||
```
|
||||
|
||||
2. **Backup database**
|
||||
```sql
|
||||
BACKUP DATABASE CredentialDb TO DISK = 'backup_pre_scheduling.bak'
|
||||
```
|
||||
|
||||
3. **Esegui migration**
|
||||
```powershell
|
||||
cd CredentialManager
|
||||
dotnet ef database update --context CredentialDbContext
|
||||
```
|
||||
|
||||
4. **Deploy nuova versione**
|
||||
```powershell
|
||||
dotnet publish --configuration Release
|
||||
```
|
||||
|
||||
5. **Avvia servizio**
|
||||
```powershell
|
||||
Start-Service -Name "DataCouplerService"
|
||||
```
|
||||
|
||||
6. **Verifica logs**
|
||||
```powershell
|
||||
Get-EventLog -LogName Application -Source "ScheduledJobService" -Newest 50
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Post-Deploy
|
||||
|
||||
- [ ] Verificare schedulazioni esistenti funzionano
|
||||
- [ ] Creare schedulazione test a intervalli
|
||||
- [ ] Monitorare logs per 24 ore
|
||||
- [ ] Verificare performance sistema
|
||||
- [ ] Validare accuratezza temporale
|
||||
|
||||
---
|
||||
|
||||
## 🔗 **File Modificati**
|
||||
|
||||
1. `CredentialManager/Models/ProfileSchedule.cs` - Modello con nuovi campi
|
||||
2. `CredentialManager/Services/ProfileScheduleService.cs` - Logica aggiornata
|
||||
3. `Data_Coupler/BackgroundServices/ScheduledJobService.cs` - Background service migliorato
|
||||
4. `CredentialManager/Migrations/[timestamp]_AddIntervalSchedulingFields.cs` - Migration database
|
||||
|
||||
---
|
||||
|
||||
**Versione**: 2.0
|
||||
**Data Implementazione**: 2 Ottobre 2025
|
||||
**Status**: ✅ Implementato e Testato
|
||||
**Sviluppatore**: Alessio Dalsanto
|
||||
Reference in New Issue
Block a user