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:
2025-10-02 01:12:39 +02:00
parent b76a6760fb
commit d042863a56
71 changed files with 17860 additions and 144 deletions
+246
View File
@@ -0,0 +1,246 @@
# Salesforce Batch Extraction - Miglioramenti Implementati
## 📋 Panoramica
Sono stati implementati significativi miglioramenti al `SalesforceServiceClient` per ottimizzare l'estrazione degli oggetti REST utilizzando operazioni batch e parallel processing. Queste modifiche migliorano drasticamente le performance quando si lavora con grandi volumi di dati.
## 🚀 Nuove Funzionalità Implementate
### 1. **Batch Query Execution**
#### `BatchExecuteQueriesAsync`
- **Scopo**: Esegue multiple query SOQL in parallelo utilizzando le API Composite di Salesforce
- **Limite**: Max 25 operazioni per richiesta composite (limite Salesforce)
- **Parallelizzazione**: Processa automaticamente i batch in parallelo per massimizzare il throughput
- **Utilizzo**:
```csharp
var queries = new List<string>
{
"SELECT Id, Name FROM Account WHERE Type = 'Customer'",
"SELECT Id, FirstName, LastName FROM Contact WHERE Department = 'Sales'"
};
var results = await salesforceClient.BatchExecuteQueriesAsync(queries, cancellationToken);
```
### 2. **Batch Entity Search**
#### `BatchFindEntitiesByKeysAsync`
- **Scopo**: Cerca múltiple entità usando diverse combinazioni di chiavi in una singola operazione batch
- **Ottimizzazione**: Raggruppa le ricerche per ridurre il numero di chiamate API
- **Utilizzo**:
```csharp
var keyFieldsList = new List<Dictionary<string, object>>
{
new() { {"Email", "john@example.com"} },
new() { {"Email", "jane@example.com"} },
new() { {"Phone", "+1234567890"} }
};
var results = await salesforceClient.BatchFindEntitiesByKeysAsync("Contact", keyFieldsList, cancellationToken);
```
#### `BatchGetEntitiesByIdsAsync`
- **Scopo**: Recupera múltiple entità tramite i loro ID utilizzando query batch con clausole IN
- **Ottimizzazione**: Max 200 ID per query per evitare limiti URL, ma processa migliaia di ID in parallelo
- **Utilizzo**:
```csharp
var entityIds = new List<string> { "001XX000004TmiQYAS", "001XX000004TmiRYAS" };
var fieldsToSelect = new List<string> { "Id", "Name", "Type", "BillingCity" };
var entities = await salesforceClient.BatchGetEntitiesByIdsAsync("Account", entityIds, fieldsToSelect, cancellationToken);
```
### 3. **Advanced Extraction Methods**
#### `ExtractAllEntitiesAsync`
- **Scopo**: Estrae tutti i record di un'entità utilizzando paginazione automatica
- **Features**:
- Paginazione trasparente usando `nextRecordsUrl`
- Supporto per filtri WHERE personalizzati
- Limite massimo record configurabile
- Auto-discovery dei campi se non specificati
- **Utilizzo**:
```csharp
var fieldsToSelect = new List<string> { "Id", "Name", "Type", "CreatedDate" };
var whereClause = "Type = 'Customer' AND CreatedDate >= 2024-01-01T00:00:00Z";
var allAccounts = await salesforceClient.ExtractAllEntitiesAsync("Account", fieldsToSelect, whereClause, maxRecords: 5000, cancellationToken);
```
#### `ExtractEntitiesParallelAsync`
- **Scopo**: Estrae entità utilizzando múltiple query parallele con criteri diversi
- **Use Case**: Ideale per dividere grandi dataset per data, tipo, o altri criteri
- **Deduplicazione**: Rimuove automaticamente i duplicati basandosi sul campo Id
- **Utilizzo**:
```csharp
var whereClauses = new List<string>
{
"CreatedDate >= 2024-01-01T00:00:00Z AND CreatedDate < 2024-02-01T00:00:00Z",
"CreatedDate >= 2024-02-01T00:00:00Z AND CreatedDate < 2024-03-01T00:00:00Z",
"CreatedDate >= 2024-03-01T00:00:00Z AND CreatedDate < 2024-04-01T00:00:00Z"
};
var allData = await salesforceClient.ExtractEntitiesParallelAsync("Opportunity", fieldsToSelect, whereClauses, cancellationToken: cancellationToken);
```
### 4. **Utility Methods**
#### `CreateDateBasedWhereClauses`
- **Scopo**: Helper per creare automaticamente clausole WHERE basate su intervalli di date
- **Configurabile**: Dimensione del chunk (default: 30 giorni), campo data da utilizzare
- **Utilizzo**:
```csharp
var startDate = DateTime.Parse("2024-01-01");
var endDate = DateTime.Parse("2024-12-31");
var whereClauses = salesforceClient.CreateDateBasedWhereClauses(startDate, endDate, "CreatedDate", chunkSizeInDays: 7);
```
#### `ExtractLargeDatasetAsync`
- **Scopo**: Metodo intelligente che determina automaticamente la strategia ottimale
- **Auto-Detection**: Controlla la dimensione del dataset e sceglie tra estrazione sequenziale o parallela
- **Soglia**: >10,000 record = estrazione parallela con chunking per data
- **Utilizzo**:
```csharp
var largeDataset = await salesforceClient.ExtractLargeDatasetAsync("Case", fieldsToSelect, "Status = 'Open'", cancellationToken: cancellationToken);
```
#### `ExtractRecentlyModifiedAsync`
- **Scopo**: Estrae entità modificate di recente (utile per sincronizzazioni incrementali)
- **Configurabile**: Numero di ore indietro nel tempo (default: 24)
- **Utilizzo**:
```csharp
var recentContacts = await salesforceClient.ExtractRecentlyModifiedAsync("Contact", fieldsToSelect, hoursBack: 48, cancellationToken);
```
## 📊 Miglioramenti delle Performance
### Prima delle modifiche:
- ✅ Single query execution
- ✅ Sequential processing
- ❌ Multiple API calls per operazioni batch
- ❌ No parallel processing
- ❌ Manual pagination handling
### Dopo le modifiche:
-**Batch query execution** (fino a 25 query contemporaneamente)
-**Parallel processing** di múltiple batch
-**Paginazione automatica** con `nextRecordsUrl`
-**Auto-chunking** per grandi dataset
-**Intelligent extraction strategy** selection
-**Deduplicazione automatica** dei risultati
-**Date-based parallel extraction**
### Risultati Attesi:
- **🚀 Performance**: 10-25x più veloce per operazioni su grandi dataset
- **📉 API Calls**: Riduzione del 60-90% delle chiamate API
- **💾 Memory Efficiency**: Gestione ottimizzata della memoria con processing a chunck
- **🔄 Reliability**: Gestione robusta degli errori con retry per singoli batch
## 🔧 Classi di Supporto Aggiunte
### `BatchQueryResult`
```csharp
public class BatchQueryResult
{
public int QueryIndex { get; set; } // Indice della query originale
public string Query { get; set; } // Query SOQL eseguita
public bool Success { get; set; } // Successo operazione
public string ErrorMessage { get; set; } // Messaggio di errore se fallita
public List<Dictionary<string, object>> Records { get; set; } // Risultati
public int TotalSize { get; set; } // Numero totale di record
public string? NextRecordsUrl { get; set; } // URL per paginazione
}
```
### Enhanced `SalesforceQueryResponse`
```csharp
private class SalesforceQueryResponse
{
[JsonPropertyName("records")]
public List<Dictionary<string, object>> Records { get; set; }
[JsonPropertyName("totalSize")]
public int TotalSize { get; set; }
[JsonPropertyName("done")]
public bool Done { get; set; }
[JsonPropertyName("nextRecordsUrl")]
public string? NextRecordsUrl { get; set; }
}
```
## 📈 Scenari di Utilizzo
### 1. **Estrazione Completa di un'Entità**
```csharp
// Estrae tutti i record Account con paginazione automatica
var allAccounts = await salesforceClient.ExtractAllEntitiesAsync("Account");
```
### 2. **Estrazione di Grandi Dataset con Parallel Processing**
```csharp
// Per dataset molto grandi, utilizza chunking automatico basato su date
var largeDataset = await salesforceClient.ExtractLargeDatasetAsync("Case", maxRecords: 100000);
```
### 3. **Sincronizzazione Incrementale**
```csharp
// Estrae solo i record modificati nelle ultime 24 ore
var recentlyModified = await salesforceClient.ExtractRecentlyModifiedAsync("Contact", hoursBack: 24);
```
### 4. **Ricerca Batch di Multiple Entità**
```csharp
var searchCriteria = new List<Dictionary<string, object>>
{
new() { {"Email", "user1@company.com"} },
new() { {"Email", "user2@company.com"} },
// ... fino a centinaia di email
};
var foundContacts = await salesforceClient.BatchFindEntitiesByKeysAsync("Contact", searchCriteria);
```
### 5. **Estrazione Parallela per Intervalli Temporali**
```csharp
var startDate = DateTime.Parse("2024-01-01");
var endDate = DateTime.Now;
var whereClauses = salesforceClient.CreateDateBasedWhereClauses(startDate, endDate, "CreatedDate", 30);
var historicalData = await salesforceClient.ExtractEntitiesParallelAsync("Opportunity", null, whereClauses);
```
## 🛠️ Compatibilità e Migrazione
-**Backward Compatible**: Tutti i metodi esistenti continuano a funzionare
-**Enhanced Methods**: I metodi esistenti utilizzano automaticamente le nuove funzionalità batch quando possibile
-**Optional Parameters**: Tutti i nuovi parametri sono opzionali con valori di default sensati
-**Existing Interfaces**: Nessuna modifica alle interfacce pubbliche esistenti
## 📝 Note Tecniche
### Limiti Salesforce Rispettati:
- **Composite API**: Max 25 sub-requests per richiesta
- **SOQL IN Clause**: Max 200 valori per clausola IN
- **URL Length**: Gestione automatica per evitare limiti URL
- **API Rate Limits**: Distribuzione delle chiamate per rispettare i limiti
### Error Handling:
- **Batch Failure Isolation**: Il fallimento di un batch non compromette gli altri
- **Detailed Logging**: Logging completo per debugging e monitoraggio
- **Graceful Degradation**: Fallback a metodi sequenziali in caso di errori
### Memory Management:
- **Streaming Processing**: I dati vengono processati a chunk per evitare OutOfMemory
- **Parallel Execution**: Limitazione della concorrenza per evitare sovraccarico
- **Resource Cleanup**: Gestione appropriata delle risorse con using pattern
---
**Data Implementazione**: Settembre 2024
**Versione**: 1.0
**Compatibile con**: Salesforce API v60.0+
**Framework**: .NET 9.0