← Все проекты уровня 5
Уровень 5 · Обработка большого числа файловВариант B

Объединение отчётов

Соберите однородные CSV-файлы в один детерминированный отчёт с дедупликацией по ключу.

Техническое задание

Объединение файлов

Создайте CLI, объединяющий CSV-файлы из заданного каталога в выходной CSV. Обязательные параметры: --input, --output, --key, --workers и --max-file-size. Выходной путь должен находиться вне входного дерева; символические ссылки не обходятся. CSV-разделитель — запятая, формат кавычек соответствует стандартному CSV. Первая строка каждого непустого файла — заголовок; заголовки должны иметь одинаковые имена и порядок во всех файлах. Несовпадение схемы — фатальная ошибка: выходной файл не должен заменяться частичным содержимым.

Аргумент --key задаёт имя непустого столбца уникальности. Повтор ключа в разных файлах или строках дедуплицируется: сохраняется первая строка по лексикографическому относительному пути файла, затем по номеру строки. Выход включает единственный заголовок и уникальные строки в порядке ключа по возрастанию. Пустые CSV пропускаются, но файл только с заголовком учитывается для проверки схемы. Строка неверной длины или пустой ключ диагностируется с файлом и строкой, пропускается, и делает результат частичным.

Ограничьте workers положительным числом; ограничьте одновременно открытые файлы тем же числом. Аргумент --max-unique задаёт положительный жёсткий предел числа уникальных ключей, хранимых в памяти. Читайте CSV построчно, а очередь файлов ограничьте буфером не более workers элементов. Поскольку итог сортируется, память для строк результата ограничена --max-unique и документируется как O(--max-unique × средний размер строки). При достижении предела новые неизвестные ключи пропускаются с диагностикой, результат помечается частичным и код возврата ненулевой; уже виденные ключи дедуплицируются обычным образом. Применяйте context.Context к обходу, чтению и ожиданию работников; CLI создаёт контекст с обработчиком SIGINT и SIGTERM. При отмене прекратите задания, дождитесь работников, закройте файлы и удалите временный выход; неполный выход не должен становиться итоговым. После полного или частичного завершения корректных входов атомарно публикуйте выход и возвращайте ненулевой код при построчных ошибках. Все результаты и диагностики детерминированы. Тестируйте отмену и конкуренцию с race detector.

Структура программы

Разместите обход и CSV-чтение в internal/csvfiles, проверку совместимости схем и выбор строки по ключу в internal/consolidate, атомарную публикацию — в отдельной файловой операции. main.go создаёт context, работников и каналы и управляет отменой. Правила дедупликации не должны зависеть от CLI; зависимости направьте к данным, не создавая циклов.

Критерии готовности

Ожидаемый результат

Проект содержит запускаемый Go CLI, README с контрактом схемы, правилом выбора дубликата и оценкой памяти, а также автономные тесты. Объединённый файл создаётся через временный файл и атомарно публикуется только после того, как операция завершена или сформирован предусмотренный частичный результат. Фатальная ошибка схемы сохраняет предыдущий выход нетронутым.

Критерии приёмки:

  • README описывает границы CSV-чтения и объединения; race-тест проверяет обработку.
  • совместимые файлы дают один заголовок;
  • дублирующий ключ сохраняет строку из лексикографически первого файла;
  • выходные строки сортируются ключом;
  • несовпадающий порядок или набор заголовков блокирует публикацию;
  • неверная ширина строки диагностируется и исключается при частичном успешном слиянии. Ограничение workers соблюдается, отмена закрывает файлы, удаляет временный выход и не оставляет горутин. Разбор потоковый, выход детерминирован, go test -race ./... проходит.

Для ориентира

Примеры входа и результата

В a.csv и b.csv есть ключи 10 и 20, а ключ 10 повторён; если a.csv лексикографически раньше, в результате остаётся строка 10 из a.csv. Если b.csv меняет порядок заголовков, схема отклоняется и заранее существующий output.csv остаётся неизменным.