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

Каталог документов

Постройте стабильный индекс файлов с метаданными и необязательными короткими текстовыми фрагментами.

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

Индексация и ограничения

Реализуйте CLI, который строит JSON-каталог документов в заданном дереве каталогов. Обязательны --root, --output, --workers и --max-files; --max-files задаёт верхний предел числа индексируемых записей. Допускается повторяемый флаг --ext для белого списка расширений, а --snippet=N включает извлечение первых N UTF-8-символов текста, где N ограничен диапазоном 1–1000. По умолчанию индексируйте обычные файлы с расширениями .txt, .md, .pdf, .docx и .csv без чтения содержимого. Расширения сравниваются без учёта регистра. Символические ссылки не обходятся и не индексируются; относительные пути в результате вычисляются от корня.

Запись JSON содержит путь, имя, расширение в нижнем регистре, размер в байтах, время изменения в UTC RFC3339 и, если включено и формат поддерживается, snippet. Фрагменты извлекайте только из UTF-8 текстовых файлов .txt, .md и .csv; для PDF и DOCX поле пропускается, а не эмулирует извлечение. Невалидный UTF-8 диагностируется и файл остаётся в индексе без фрагмента. Данные отсортируйте по относительному пути лексикографически перед публикацией, сериализуйте детерминированно с отступами и завершающим переводом строки.

Не читайте все документы целиком: метаданные получают через файловую систему, текст читается не более чем до объёма, достаточного для заданных символов, плюс небольшой запас для UTF-8. Канал заданий ограничен workers элементами, число записей не может превысить --max-files; если обнаружен ещё один подходящий файл сверх --max-files, остановите обход и верните ненулевой код с неполным индексом. Одновременно обрабатывайте не более workers файлов и ограничьте число открытых файлов этим же пределом. Проверяйте context.Context при обходе, чтении и получении задач. CLI обязан создавать context через обработчик SIGINT и SIGTERM. При отмене прекращайте новые задачи, закрывайте файлы и дожидайтесь работников; отменённый индекс не публикуйте, временный файл удаляйте и сохраняйте прежний output, сообщая о неполноте только в диагностике. Ошибки отдельных файлов выводите в stderr и формируйте частичный индекс с ненулевым кодом; ошибка корня фатальна. Запись делайте во временный файл рядом с output и атомарно переименовывайте только после завершения индексации. README объясняет неполноту и ограничения извлечения; требуются тесты и race-проверка.

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

В internal/indexfiles реализуйте обход, извлечение метаданных и ограниченных текстовых фрагментов; в internal/catalog — поля записи, сортировку и лимиты индекса. Оставьте main.go создание контекст, отменяемый сигналом, запуск ограниченных workers и атомарную публикацию. Пакет правил получает данные через файловые функции, без циклических зависимостей.

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

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

Сдайте запускаемый Go-модуль с CLI, JSON-форматом результата, README о поддерживаемых расширениях и ограничениях фрагмента, и детерминированными офлайн-тестами. Обход, файловые чтения и запись используют отменяемый контекст; ограничение workers задаёт реальный верхний предел параллельных операций. Выход является валидным JSON и публикуется атомарно.

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

  • README описывает границы индексатора и каталога; race-тест проверяет обработку.
  • путь и метаданные обычного файла присутствуют;
  • расширение в индексе нормализовано;
  • .MD включается при фильтре .md;
  • символическая ссылка пропускается;
  • фрагмент .txt ограничен запрошенным числом Unicode-символов;
  • PDF индексируется без текстового фрагмента. Ошибка отдельного файла даёт диагностируемый частичный индекс и ненулевой код;
  • отмена завершает работников, удаляет временный файл и сохраняет прежний output. Порядок записей повторяем, а go test -race ./... проходит без гонок.

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

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

Файл notes/Plan.MD размером 42 байта при --ext .md попадает в индекс с расширением .md и относительным путём notes/Plan.MD. При --snippet 6 текст «Привет, мир» даёт первые 6 Unicode-символов «Привет»; PDF записывается в индекс без snippet.