# distbuild В этом задании вам нужно будет реализовать систему распределённой сборки. Система сборки получает на вход граф сборки и файлы с исходным кодом. Результатом сборки являются исполняемые файлы и stderr/stdout запущенных процессов. ## Граф сборки Граф сборки состоит из джобов. Каждый джоб описывает команды, которые нужно запустить на одной машине, вместе со всеми входными файлами, которые нужны этим командам для работы. Джобы в графе сборки запускают произвольные команды. Например, вызывать компилятор, линкер или запускать тесты. Команды внутри джоба могут читать файлы с файловой системы. Мы будем различать два вида файлов: - Файлы с исходным кодом с машины пользователя. - Файлы, которые породили другие джобы. Команды внутри джоба могут писать результаты своей работы в файлы на диске. Выходные файлы обязаны находиться внутри `OUTPUT_DIR` директории. ```go package graph import "crypto/sha1" // ID задаёт уникальный идентификатор джоба. // // Мы будем использовать sha1 хеш, поэтому ID будет занимать 20 байт. type ID [sha1.Size]byte // Job описывает одну вершину графа сборки. type Job struct { // ID задаёт уникальный идентификатор джоба. // // ID вычисляется как хеш от всех входных файлов, команд запуска и хешей зависимых джобов. // // Выход джоба целиком опеределяется его ID. Это важное свойство позволяет кешировать // результаты сборки. ID ID // Name задаёт человекочитаемое имя джоба. // // Например: // build gitlab.com/slon/disbuild/pkg/b // vet gitlab.com/slon/disbuild/pkg/a // test gitlab.com/slon/disbuild/pkg/test Name string // Inputs задаёт список файлов из директории с исходным кодом, // которые нужны для работы этого джоба. // // В типичном случае, тут будут перечислены все .go файлы одного пакета. Inputs []string // Deps задаёт список джобов, выходы которых нужны для работы этого джоба. Deps []ID // Cmds описывает список команд, которые нужно выполнить в рамках этого джоба. Cmds []Cmd } // Cmd описывает одну команду сборки. // // Есть несколько видов команд. Все виды команд описываются одной структурой. // Реальный тип определяется тем, какие поля структуры заполнены. // // exec - выполняет произвольную команду // cat - записывает строку в файл // // Все строки в описании команды могут содержать в себе на переменные. Перед выполнением // реальной команды, переменные заменяются на их реальные значения. // // {{OUTPUT_DIR}} - абсолютный путь до выходной директории джоба. // {{SOURCE_DIR}} - абсолютный путь до директории с исходными файлами. // {{DEP:f374b81d81f641c8c3d5d5468081ef83b2c7dae9}} - абсолютный путь до директории, // содержащей выход джоба с id f374b81d81f641c8c3d5d5468081ef83b2c7dae9. type Cmd struct { // Exec описывает команду, которую нужно выполнить. Exec []string // Environ описывает переменные окружения, которые необходимы для работы команды из Exec. Environ []string // WorkingDirectory задаёт рабочую директорию для команды из Exec. WorkingDirectory string // CatTemplate задаёт шаблон строки, которую нужно записать в файл. CatTemplate string // CatOutput задаёт выходной файл для команды типа cat. CatOutput string } ``` ## Архитектура системы Наша система будет состоять из трех компонент. * Клиент - процесс запускающий сборку. * Воркер - процесс запускающий команды компиляции и тестирования. * Координатор - центральный процесс в системе, общается с клиентами и воркерами. Раздаёт задачи воркерам. Типичная сборка выглядит так: 1. Клиент подключается к координатору, посылает ему граф сборки и входные файлы для графа сборки. 2. Кооринатор сохраняет граф сборки в памяти и начинает его исполнение. 3. Воркеры начинают выполнять вершины графа, пересылая друг другу выходные директории джобов. 4. Результаты работы джобов скачиваются на клиента. ## Протокол: Клиент <-> Координатор ## Протокол: Координатор <-> Воркер ## Кеширование ### Кеш исходного кода ### Кеш артефактов ## Тестирование