← Все проекты уровня 15
Уровень 15 · Платформа выполнения задачВариант C

Платформа вычислений

Распределённые вычисления с объединением результатов, отменой и восстановлением исполнителей.

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

Виды задач и разбиение

Создайте платформу вычислений на Go. Поддерживается одна детерминированная операция: статистика CSV-набора (количество строк, сумма и минимум/максимум числовой колонки). Запрос содержит CSV до 50 MiB, колонку, delimiter и 1–64 chunks. CSV разбирается с поддержкой quoted multiline полей, chunks считаются по логическим CSV-записям, а не физическим строкам. Sum — checked int64; overflow завершает job как failed, пустой набор даёт count=0, sum=0, min=null, max=null. Части охватывают последовательные диапазоны CSV-записей; их ID строится из job ID и номера диапазона. Пустые числа пропускаются, нечисловое значение завершает chunk как invalid_input с номером строки. Сводка части содержит count, sum, min, max и digest; при объединении проверяются порядок частей и одна принятая сводка на диапазон.

REST и состояние

Локальный seed создаёт compute_user с токеном в Authorization header; job доступны только создавшему их пользователю и локальному оператору. POST /api/v1/jobs создаёт задачу по idempotency key; одинаковые payload и key возвращают прежний job, изменившийся файл или параметры дают 409. GET /jobs/{id} возвращает queued/running/merging/succeeded/failed/cancelled, общий progress, количество завершённых chunks и итог. GET /jobs/{id}/chunks/{chunk_id} показывает attempt и state. POST /jobs/{id}/cancel останавливает незапущенные chunks и направляет отмену работающим; POST /jobs/{id}/retry повторяет recoverable chunks только для failed job. Один job имеет revision и неизменяемый input digest. Итог доступен лишь после успешного объединения всех частей; частичный результат отмечен отдельно и не считается success. При отмене во время merge первой фиксируется либо отмена без результата, либо объединение со статусом succeeded.

Исполнители и восстановление

PostgreSQL хранит задания, фрагменты, попытки, права обработки, heartbeat, контрольные позиции, частичные и итоговый результаты, outbox и аудит. Координатор и два исполнителя запускаются в Docker Compose. Исполнитель берёт до двух фрагментов; общий предел — два на исполнителя, максимум 8. Право обработки действует 30 секунд с heartbeat каждые 10 секунд; по истечении повторяется только восстанавливаемый фрагмент. Невалидный вход не повторяется, временная ошибка чтения каталога допускает два повтора, гибель исполнителя — один. Фрагмент, результат и контрольная позиция фиксируются одной транзакцией с проверкой поколения. Очередь — максимум 256 фрагментов; новая задача, не помещающаяся целиком, получает 429 без частичной записи. Архив хранится отдельно; временные файлы до 100 MiB удаляются через сутки. SQL timeout 3 секунды; команды пользователя не запускаются.

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

Координатор и исполнители запускаются раздельно; ядро делит записи, считает и объединяет сводки, транспорт и SQL-хранилище остаются внешними границами. main.go только загружает конфигурацию, связывает зависимости и управляет запуском. Пакеты без циклов, общих utils и интерфейсов без потребителя. README показывает зависимости; тесты ядра без HTTP/БД, интеграционные отдельно.

Наблюдаемость и приёмка

Каждый API ответ содержит trace_id, связанный в журналах с job_id, chunk_id, attempt_id и worker_id. Метрики отображают очередь chunks, прогресс job, возраст права обработки, heartbeat, повторы, время merge и пиковую память. Compose запускает два исполнителя и координатор; тестовый набор содержит пустые значения, отрицательные числа, последние неполные chunk, malformed row и повторные запросы. Тесты завершают исполнителя после вычисления до фиксации результата, запускают второго исполнителя и проверяют защиту от устаревшего исполнителя; отдельно останавливают координатор до merge и после фиксации. Пиковая подача, превышающая 256 chunks, проверяет атомарное отклонение новой job. Критерии готовности: итоговая сумма и min/max совпадают с последовательным контрольным подсчётом, прогресс монотонен, каждое завершённое задание имеет одну принятую сводку на chunk, потерянное право обработки восстановлено максимум за 40 секунд, cancel завершён и не публикует частичный итог. Воспроизводимый отчёт обрабатывает 1 000 000 строк, фиксирует время, пиковую память, chunks и конфигурацию, а затем завершает исполнителя до фиксации chunk и показывает восстановление и связанные идентификаторы трассировки.

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

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

Проверяемый результат

  • README показывает границы и направление зависимостей; main.go только связывает конфигурацию и запуск; модульные тесты ядра обходятся без HTTP и БД, интеграционные тесты отделены.
  • Compose запускает координатор, PostgreSQL и два исполнителя; задание статистики CSV возвращает количество, сумму, минимум и максимум.
  • Итог совпадает с последовательным локальным подсчётом на фиксированном наборе и становится виден только после merge.
  • API показывает chunk progress, trace_id, попытки, job state и cancellation; повтор запроса с тем же ключом не создаёт job.
  • Сбой исполнителя восстанавливает chunk в пределах 40 секунд; проверка поколения попытки отвергает устаревшую запись, а retry выполняется только для recoverable failure.
  • Переполнение очереди атомарно отклоняет job и не оставляет частичные chunks; общий объём данных и память ограничены.
  • Офлайн-тесты проверяют границы разделения, неверную строку, неполный фрагмент, перезапуск координатора, объединение и гонку отмены.
  • Отчёт фиксирует фактические время и пиковую память для 1 000 000 строк на описанном стенде; панели и метрики показывают очередь, retries, leases и длительность объединения.