Skip to content

perf+feat(import): fix O(n^2) CSV read, smaller batch, progress bar#1836

Open
AllWorkNoPlay-95 wants to merge 5 commits into
devcode-it:masterfrom
AllWorkNoPlay-95:feat/csv-import-performance
Open

perf+feat(import): fix O(n^2) CSV read, smaller batch, progress bar#1836
AllWorkNoPlay-95 wants to merge 5 commits into
devcode-it:masterfrom
AllWorkNoPlay-95:feat/csv-import-performance

Conversation

@AllWorkNoPlay-95

@AllWorkNoPlay-95 AllWorkNoPlay-95 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Descrizione

Migliora performance, robustezza e UX dell'importazione CSV (modules/import), in particolare per file grandi (migliaia di righe).

1. Lettura del batch in un'unica passata — fix O(n²)
CSVImporter::getRows() leggeva ogni riga con $this->csv->fetchOne($offset + $i) in un ciclo. league/csv::fetchOne() ri-scorre il file dall'inizio ad ogni chiamata, quindi l'importazione era quadratica (~12,5 milioni di parse di riga per 5000 righe, con rallentamento progressivo verso la fine). Ora il batch viene letto una sola volta con Statement::create()->offset()->limit().

Risultato misurato: testato su un'importazione reale di 5000+ anagrafiche clienti, l'avanzamento che prima richiedeva diversi minuti ora si completa in pochi secondi.

2. Dimensione del batch 500 → 100
Richieste più brevi (meno rischio di timeout del proxy / PHP su file grandi) e aggiornamenti di avanzamento più frequenti.

3. Progress bar + messaggi di errore leggibili (modules/import/edit.php)

  • Lo spinner a tutto schermo è sostituito da un overlay con progress bar che si aggiorna dopo ogni batch (righe processate / totale + percentuale). Il totale arriva dal nuovo CSVImporter::getTotalRows().
  • In caso di errore della richiesta, il callback error di ajaxSubmit concatenava l'oggetto jqXHR in una stringa, mostrando [object Object]. Ora viene mostrato il messaggio reale (responseJSON.messageresponseTextstatusText).

4. Avvisi all'utente nell'overlay di avanzamento

  • Avviso a non chiudere/ricaricare la pagina finché l'importazione non è completata.
  • Avviso dinamico (solo per import anagrafiche con "Geolocalizzazione automatica" attiva) che segnala tempi più lunghi, dato che ogni riga viene geolocalizzata tramite un servizio online.
Screenshot 2026-06-08 alle 12 11 20 Screenshot 2026-06-08 alle 13 08 29

Nessuna nuova dipendenza richiesta. Nessuna modifica allo schema.

Risolve: ISSUE 1459

Tipologia

  • Bug fix (cambiamenti minori che risolvono una issue)
  • Nuova funzionalità (cambiamenti minori che aggiungono una nuova funzionalità)

Checklist

  • Il codice segue le linee guida del progetto
  • Ho commentato il codice, in particolare nelle parti più complesse
  • Ho aggiornato di conseguenza la documentazione (se presente)
  • Il codice non genera warnings

Nota sul check Codacy (da ignorare)

Codacy segnala su alcune righe "All output should be run through an escaping function … found 'tr'" (es. modules/import/edit.php, la riga con tr('Importazione in corso...')).

È un falso positivo: la regola proviene dai WordPress Coding Standards (WordPress.Security.EscapeOutput), che pretende esc_html()/esc_attr() e non riconosce tr() come funzione di escaping. OSM non è WordPress e usa tr() come funzione standard di traduzione/output in tutto il progetto (centinaia di occorrenze). Le righe introdotte qui seguono esattamente la stessa convenzione già presente nello stesso file (es. le righe pre-esistenti con tr('Informazioni importanti:'), tr('Campi obbligatori (*):'), ecc.). Inoltre gli argomenti di tr() sono stringhe statiche, non input utente.

La segnalazione può quindi essere ignorata.

getRows() called league/csv fetchOne($offset+$i) in a loop, and fetchOne re-scans the file from the start on every call, making imports O(n^2) (~12.5M line-parses for 5000 rows). Read each batch once via Statement::offset()->limit(). Add getTotalRows() so the UI can compute import progress.
Shorter per-request work (less risk of proxy/PHP timeouts on large files) and more frequent progress updates.
Replace the full-screen spinner with a progress overlay that updates after each batch (processed/total rows + percentage). Show the actual server error instead of '[object Object]' when an import request fails.
@AllWorkNoPlay-95 AllWorkNoPlay-95 marked this pull request as draft June 8, 2026 09:44
Anagrafiche imports geolocate each row via an online service when 'Geolocalizzazione automatica' is enabled, which slows the import. Show a dynamic notice in the progress overlay only when the setting is active for an anagrafiche import.
@AllWorkNoPlay-95 AllWorkNoPlay-95 marked this pull request as ready for review June 8, 2026 10:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant