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
9.5 KiB
9.5 KiB
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:
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:
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:
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
- Paginazione trasparente usando
- Utilizzo:
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:
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:
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:
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:
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
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
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à
// Estrae tutti i record Account con paginazione automatica
var allAccounts = await salesforceClient.ExtractAllEntitiesAsync("Account");
2. Estrazione di Grandi Dataset con Parallel Processing
// Per dataset molto grandi, utilizza chunking automatico basato su date
var largeDataset = await salesforceClient.ExtractLargeDatasetAsync("Case", maxRecords: 100000);
3. Sincronizzazione Incrementale
// Estrae solo i record modificati nelle ultime 24 ore
var recentlyModified = await salesforceClient.ExtractRecentlyModifiedAsync("Contact", hoursBack: 24);
4. Ricerca Batch di Multiple Entità
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
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