# Fix: Pre-Discovery Forced Update Loop ## πŸ› Problema Identificato **Descrizione**: I record con associazioni Pre-Discovery venivano forzatamente aggiornati ad ogni trasferimento, anche quando i dati non erano cambiati. **Causa Root**: Il flag `isPreDiscoveryAssociation` rimaneva `true` anche dopo il primo aggiornamento, causando un loop infinito di aggiornamenti forzati che bypassavano il controllo hash. ```csharp // ❌ LOGICA ERRATA (PRIMA DELLA FIX) if (isPreDiscoveryAssociation) { // PROBLEMA: Forza SEMPRE l'aggiornamento, anche ai trasferimenti successivi recordsForUpdate.Add(...); } else { // Il controllo hash viene eseguito solo per le associazioni NON Pre-Discovery if (existingHash != currentHash) recordsForUpdate.Add(...); } ``` **Impatto**: - Record aggiornati inutilmente ad ogni esecuzione - Spreco di chiamate API - Consumo quota Salesforce non necessario - Log inquinati da aggiornamenti fantasma - Performance degradate ## βœ… Soluzione Implementata ### 1. Biforcazione Controllo Hash Corretta **File**: `DataCoupler.razor.cs` - Metodo `StartDataTransferWithComposite` **Cambiamento**: Biforcazione intelligente basata sul flag Pre-Discovery. ```csharp // βœ… LOGICA CORRETTA (DOPO LA FIX) if (existingAssociation != null && existingAssociation.IsActive) { var isPreDiscoveryAssociation = AssociationService.IsPreDiscoveryAssociation(existingAssociation); // PRIMA SINCRONIZZAZIONE: Forza aggiornamento (ignora hash) if (isPreDiscoveryAssociation) { recordsForUpdate.Add(...); // βœ… FORZA aggiornamento prima volta Logger.LogInformation("πŸ”„ PRIMA SINCRONIZZAZIONE (Pre-Discovery) - AGGIORNAMENTO FORZATO"); } else { // SINCRONIZZAZIONI SUCCESSIVE: Controllo hash standard if (!string.IsNullOrEmpty(existingHash) && existingHash == currentHash) { recordsSkipped.Add(...); // βœ… SALTA se hash identico } else { recordsForUpdate.Add(...); // βœ… AGGIORNA se hash diverso } } } ``` **Vantaggi**: - βœ… Prima sincronizzazione Pre-Discovery β†’ **sempre aggiornato** (hash ignorato) - βœ… Trasferimenti successivi β†’ controllo hash standard - βœ… Flag Pre-Discovery resettato dopo primo aggiornamento ### 2. Reset Flag Pre-Discovery **File**: `DataCoupler.razor.cs` - Metodo `UpdateAssociationHashAsync` **Cambiamento**: Dopo il primo aggiornamento, rimuove il flag `PreDiscovery` da `AdditionalInfo`. ```csharp // πŸ”„ RESET PRE-DISCOVERY FLAG if (!string.IsNullOrEmpty(existingAssociation.AdditionalInfo)) { var additionalInfo = JsonSerializer.Deserialize>( existingAssociation.AdditionalInfo); if (additionalInfo?.ContainsKey("PreDiscovery") == true) { additionalInfo.Remove("PreDiscovery"); // βœ… Rimuove il flag existingAssociation.AdditionalInfo = JsonSerializer.Serialize(additionalInfo); Logger.LogDebug("Flag Pre-Discovery resettato per entityId {EntityId}", entityId); } } ``` **Vantaggi**: - βœ… Flag Pre-Discovery presente solo fino al primo aggiornamento - βœ… Associazione "normalizzata" dopo la prima sincronizzazione - βœ… Garbage collection del flag non piΓΉ necessario ## πŸ” Flusso Completo Pre-Discovery (Corretto) ### Scenario: Record esistente in destinazione, nessuna associazione #### **Prima Esecuzione (Pre-Discovery Discovery)** 1. **Pre-Discovery Search** β†’ Trova record esistente in Salesforce 2. **Crea Associazione** con `AdditionalInfo.PreDiscovery = true` e `Data_Hash = NULL` 3. **Controllo Hash**: `existingHash = NULL` β†’ **AGGIORNA** (primo sync) 4. **Update Record** in Salesforce 5. **Update Hash** + **RESET FLAG PRE-DISCOVERY** - Salva nuovo hash - Rimuove `PreDiscovery` da `AdditionalInfo` #### **Seconda Esecuzione (Stesso Dato)** 1. **Trova Associazione** (giΓ  esistente, senza flag Pre-Discovery) 2. **Controllo Hash**: `existingHash == currentHash` β†’ **SALTA** βœ… 3. Nessun aggiornamento, nessuna chiamata API #### **Terza Esecuzione (Dato Modificato)** 1. **Trova Associazione** (esistente) 2. **Controllo Hash**: `existingHash != currentHash` β†’ **AGGIORNA** 3. **Update Record** in Salesforce 4. **Update Hash** ## πŸ“Š Risultati Attesi ### Prima della Fix ``` Esecuzione 1: 10 record aggiornati (Pre-Discovery) Esecuzione 2: 10 record aggiornati (FORZATO) ❌ Esecuzione 3: 10 record aggiornati (FORZATO) ❌ ... ``` ### Dopo la Fix ``` Esecuzione 1: 10 record aggiornati (Pre-Discovery - Primo Sync) Esecuzione 2: 0 record aggiornati, 10 saltati (Hash identico) βœ… Esecuzione 3: 0 record aggiornati, 10 saltati (Hash identico) βœ… Esecuzione 4: 3 record aggiornati, 7 saltati (Solo 3 modificati) βœ… ``` ## πŸ§ͺ Come Testare ### Test 1: Verifica Primo Aggiornamento Pre-Discovery 1. Crea un record manualmente in Salesforce (es. Contact con Email) 2. Esegui trasferimento con lo stesso record dalla sorgente 3. **Atteso**: Record aggiornato con log `πŸ”„ PRIMA SINCRONIZZAZIONE (Pre-Discovery)` ### Test 2: Verifica Skip su Secondo Trasferimento 1. Esegui di nuovo lo stesso trasferimento (dati identici) 2. **Atteso**: Record saltato con log `βœ… HASH IDENTICO - Record X saltato` ### Test 3: Verifica Reset Flag Pre-Discovery 1. Dopo il primo aggiornamento, controlla il database: ```sql SELECT AdditionalInfo FROM KeyAssociations WHERE DestinationId = 'xxx'; ``` 2. **Atteso**: Il campo `AdditionalInfo` NON deve contenere `"PreDiscovery"` ### Test 4: Verifica Aggiornamento su Dato Modificato 1. Modifica un campo nel record sorgente 2. Esegui trasferimento 3. **Atteso**: Record aggiornato con log `⚠️ HASH DIVERSO` ## πŸ“ Log di Debug ### Log Informativi (sempre visibili) ``` πŸ” CONFRONTO HASH - Record 1: πŸ“Œ Hash esistente: 1A2B3C4D... πŸ“Œ Hash corrente: 1A2B3C4D... βœ… HASH IDENTICO - Record 1 saltato ``` oppure ``` πŸ” CONFRONTO HASH - Record 1: πŸ“Œ Hash esistente: NULL πŸ“Œ Hash corrente: 1A2B3C4D... πŸ”„ PRIMA SINCRONIZZAZIONE (Pre-Discovery) - Record 1 marcato per aggiornamento ``` oppure ``` πŸ” CONFRONTO HASH - Record 1: πŸ“Œ Hash esistente: 1A2B3C4D... πŸ“Œ Hash corrente: 9Z8Y7X6W... ⚠️ HASH DIVERSO - Record 1 marcato per aggiornamento ``` ### Log Debug (solo Development) ``` COMPOSITE: Flag Pre-Discovery resettato per entityId 001xxx... COMPOSITE: Hash associazione aggiornato per entityId 001xxx... - Nuovo hash: 1A2B3C4D... ``` ## πŸ”§ File Modificati ### 1. `DataCoupler.razor.cs` - Linee 2776-2808 **Prima**: - Biforcazione logica: `if (isPreDiscoveryAssociation)` β†’ forza update - `else` β†’ controllo hash **Dopo**: - Controllo hash UNIFICATO per tutti i record - Log differenziato solo per debugging ### 2. `DataCoupler.razor.cs` - Linee 3180-3203 **Prima**: - Aggiorna solo hash e timestamp **Dopo**: - Aggiorna hash e timestamp - **+ Reset flag Pre-Discovery** (rimuove da `AdditionalInfo`) ## ✨ Benefici della Fix 1. **Performance** ⚑ - Riduzione drastica aggiornamenti inutili - Meno chiamate API Salesforce - Minor consumo quota 2. **AffidabilitΓ ** πŸ›‘οΈ - Comportamento coerente e prevedibile - Controllo hash funzionante sempre - Nessun loop infinito 3. **ManutenibilitΓ ** πŸ”§ - Logica semplificata (no biforcazioni) - Log chiari e informativi - Codice piΓΉ leggibile 4. **Costi** πŸ’° - Riduzione consumo API Salesforce - Minor carico su database - Ottimizzazione risorse ## πŸ“š Riferimenti - **Sistema Pre-Discovery**: `PRE_DISCOVERY_SYSTEM.md` - **Sistema Hash**: `HASH_CALCULATION_ALIGNMENT.md` - **Sistema Associazioni**: `GESTIONE_ASSOCIAZIONI_AVANZATA.md` --- **Data Fix**: 27 Ottobre 2024 **Versione**: 1.0 **Impatto**: Critico - Sistema di controllo hash ora completamente funzionante **Breaking Changes**: Nessuno - Retrocompatibile