Вы разрабатываете сервис хранения файлов.
На сервер по HTTP PUT присылают файл, его надо разрезать на 5 равных частей и сохранить на 5 серверах хранения. При запросе HTTP GET нужно достать куски, склеить и отдать файл.
Имеем следующее
- Один сервер для HTTP-запросов
- Несколько серверов (>5) для хранения кусков файлов
Ограничения
- Реализовать тестовый модуль для сервиса, который обеспечит проверку его функционала
- Сервера для хранения могут добавляться в систему в любой момент, но не могут удаляться из системы
- Предусмотреть равномерное заполнение серверов хранения
- Можно задавать вопросы и уточнять условия задачи
- Код разместить в Github
- Код может быть несовершенным — нам важно понять образ вашего мышления и подходов к решению задачи
- Что подразумевается под несколькими серверами для хранения кусков файлов? Необходимо реализовать эти сервера? Или подразумевается, что есть некоторые хранилища в размере 5 штук и более, которые необходимо использовать для хранения и выборки данных через абстракцию, а как оно в реальности будет работать - не так важно?
- Как подразумевается добавление хранилища? Требуется ли реализовывать функционал добавления?
- Если требуется реализация добавления хранилища, нужны пояснения по тому, как это должно происходить: это конфигурирование с последующей перезагрузкой сервиса, либо какая-то операция, которая обеспечит добавление хранилища на лету?
- Тест ожидается интеграционным на put|get или юнит-тесты на функционал сервиса?
Ответы на вопросы не были получены, ввиду этого, предлагаю следующее решение.
- Реализация мультистораджа для наглядности сделана in memory с конфигурированием при старте (параметр
--storagesAmount
, принимающий значение количества хранилищ). Сделан интерфейс для хранилища файлов, что позволит дальше реализовать мультисторадж как заблагорассудится. - Добавление стораджа не сделано. Хотите увеличить количество хранилищ -- перезапускаем сервис с другим параметром.
- Тест реализован в виде http request'а ( test/httpRequests/files.http ). Можно запустить в jetBrains - там всё для этого сделано. На критический функционал написаны unit-тесты.
- Проверки на количество стораджей при запуске сервиса нет - лишь при записи файла будет ошибка. Это на откуп человека, который будет запускать скрипт.
Сервис формируется по подходу API-first (другие названия: design/contract-first) - подход, при котором сначала описывается контракт на одном из IDL (в данном случае - OpenAPI), а уже потом создается код. Это позволяет держать в актуальном состоянии спецификацию API, на основе которой генерируется серверная часть. Сторонние же сервисы на основе спецификации уже могут генерировать клиентскую часть.
Спецификация API можно найти в файле api/openapi/app.yaml.
На основе спецификации сгенерирован сервер и сформированы хэндлеры.
В качестве web-сервеа выбран chi.
За запуск приложения отвечает cobra. Команда для запуска описана в cmd/run.go.
Приложение сформировано на базе DDD (Domain-driven Design) с допущениями и упрощениями ввиду специфики задачи. В папке internal/domain описаны сущности домена (основной агрегат с которым имеем дело - файл), команды и запросы (в парадигме CQRS), работающие с сущностями домена и репозиторий, в котором реализована логика работы с хранением файлов по условиям задания в памяти.
Сервисный слой приложения, который связывает API и внутренние слои, описывается в internal/domain/application.go.
В internal/pkg реализованы функции работы с содержимым файла (разбиение и объединение контента).
Детали, нюансы уже будут видны по коду.
Вопросы/комментарии приветствуются.
go run . run -s 5
go test -race ./...