Skip to content

bug(csv): synchronous string generation in resultGridAsCsv freezes UI isolate and risks memory exhaustion on large datasets #277

Description

@ZhuchkaTriplesix

Summary / Описание проблемы

При сохранении или копировании результатов SQL-запроса в формате CSV (saveResultGridCsvFile или буфер обмена в results_tab.dart), генерация CSV-текста выполняется синхронно в основном UI-изоляте функцией resultGridAsCsv:

String resultGridAsCsv(List<String> columns, List<List<String>> rows) {
  final lines = <String>[
    columns.map(escapeCsvField).join(','),
    ...rows.map((r) { ... return cells.join(','); }),
  ];
  return lines.join('\n');
}

При экспорте выборок большого объема (например, 50 000 — 100 000 строк из PostgresTableView или окна Results), resultGridAsCsv мгновенно создает в оперативной памяти миллионы промежуточных объектов строк (List.generate + .map + .join), что приводит к полной заморозке (freeze) интерфейса Flutter на несколько секунд, а на слабых машинах вызывает аварийное завершение процесса по исчерпанию памяти (OutOfMemoryError).

Scope & Component

  • Scope: desktop
  • Component: Core / CSV Exporter & Table View
  • Kind: bug
  • Severity: medium
  • Detected in version: dev / 0.5.0

Местоположение в коде

  • Файлы:
    • lib/core/csv/result_grid_csv.dart (строки ~16-29, функция resultGridAsCsv)
    • lib/core/csv/save_result_grid_csv.dart (строка ~25)
    • lib/features/main_screen/results_tab.dart (строки ~87 и ~126)

Шаги воспроизведения

  1. Выполнить SQL-запрос, возвращающий 50 000+ строк из широкой таблицы.
  2. В панели результатов (ResultsTab) нажать Save as CSV… или Copy as CSV.
  3. Фактический результат: Интерфейс приложения полностью зависает (не реагирует на клики и перерисовку) на время генерации одной гигантской строки.
  4. Ожидаемый результат: Экспорт в файл (saveResultGridCsvFile) должен выполняться потоково (File.openWrite() с постепенной записью чанков без накопления в памяти), а генерация строки для буфера обмена должна происходить в фоновом изоляте (compute(...)) или с ограничением максимального числа копируемых строк.

Acceptance Criteria / Критерии приемки

  • Для экспорта в файл (saveResultGridCsvFile) реализована потоковая запись на диск через IOSink / File.openWrite(), исключающая формирование всего CSV в одной переменной String.
  • Тяжелые операции форматирования CSV для буфера обмена вынесены в фоновый изолят (compute(...) или Isolate.run), чтобы не блокировать главный UI-поток Flutter.

Metadata

Metadata

Labels

bugSomething isn't workingcoreCore library logic and servicesuiUser interface components and widgets

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions