Требования к заданию (часть первая)
Пользователь хочет считать арифметические выражения.
Он вводит строку 2 + 2 * 2 и хочет получить в ответ 6.
Но наши операции сложения и умножения (также деления и вычитания) выполняются "очень-очень" долго.
Поэтому вариант, при котором пользователь делает http-запрос и получает в качетсве ответа результат, невозможна.
Более того: вычисление каждой такой операции в нашей "альтернативной реальности" занимает "гигантские" вычислительные мощности.
Соответственно, каждое действие мы должны уметь выполнять отдельно и масштабировать эту систему можем добавлением вычислительных мощностей в нашу систему в виде новых "машин".
Поэтому пользователь, присылая выражение, получает в ответ идентификатор выражения и может с какой-то периодичностью уточнять у сервера "не посчиталость ли выражение"?
Если выражение наконец будет вычислено - то он получит результат.
Помните, что некоторые части арфиметического выражения можно вычислять параллельно.
- Форма ввода арифметического выражения. Пользователь вводит арифметическое выражение и отправляет POST http-запрос с этим выражением на back-end. Примечание: Запросы должны быть идемпотентными. К запросам добавляется уникальный идентификатор. Если пользователь отправляет запрос с идентификатором, который уже отправлялся и был принят к обработке - ответ 200. Возможные варианты ответа:
- 200 - Выражение успешно принято, распаршено и принято к обработке
- 400 - Выражение невалидно
- 500 - Что-то не так на back-end. В качестве ответа нужно возвращать id принятного к выполнению выражения.
- Страница со списком выражений в виде списка с выражениями. Каждая запись на странице содержит статус, выражение, дату его создания и дату заверщения вычисления. Страница получает данные GET http-запрсом с back-end-а
- Страница со списком операций в виде пар: имя операции + время его выполнения (доступное для редактирования поле). Как уже оговаривалось в условии задачи, наши операции выполняются "как будто бы очень долго". Страница получает данные GET http-запрсом с back-end-а. Пользователь может настроить время выполения операции и сохранить изменения.
- Страница со списком вычислительных можностей. Страница получает данные GET http-запросом с сервера в виде пар: имя вычислительного ресурса + выполняемая на нём операция.
- Оркестратор может перезапускаться без потери состояния. Все выражения храним в СУБД.
- Оркестратор должен отслеживать задачи, которые выполняются слишком долго (вычислитель тоже может уйти со связи) и делать их повторно доступными для вычислений.
- Сервер, который принимает арифметическое выражение, переводит его в набор последовательных задач и обеспечивает порядок их выполнения. Далее будем называть его оркестратором.
- Вычислитель, который может получить от оркестратора задачу, выполнить его и вернуть серверу результат. Далее будем называть его агентом.
Сервер, который имеет следующие endpoint-ы:
- Добавление вычисления арифметического выражения.
- Получение списка выражений со статусами.
- Получение значения выражения по его идентификатору.
- Получение списка доступных операций со временем их выполения.
- Получение задачи для выполения.
- Приём результата обработки данных.
Демон, который получает выражение для вычисления с сервера, вычисляет его и отправляет на сервер результат выражения. При старте демон запускает несколько горутин, каждая из которых выступает в роли независимого вычислителя. Количество горутин регулируется переменной среды.
Требования к заданию (часть вторая)
Продолжаем работу над проектом `Распределенный калькулятор`.В этой части работы над проектом реализуем персистентность и многопользовательский режим.
-
Добавляем регистрацию пользователя. В ответ получает 200 в случае успеха. В противном случае - 401.
POST /signup { "login": "login_value", "password": "password_value" }
-
Добавляем вход. В ответ получает 200 и JWT токен для последующей авторизации. В противном случае - 403.
POST /login { "login": "login_value", "password": "password_value" }
- Весь реализованный ранее функционал работает как раньше, только в контексте конкретного пользователя.
- 20 баллов.
- У кого выражения хранились в памяти - переводим хранение в СУБД.
- 20 баллов
- У кого общение вычислителя и сервера вычислений было реализовано с помощью HTTP - переводим взаимодействие на GRPC.
- 10 баллов
- Покрытие проекта модульными тестами
- 10 баллов
- Покрытие проекта интеграционными тестами
- 10 баллов
- проект находится на GitHub
- к проекту прилагается файл с подробным описанием (как запустить, проверить функционал и протестировать)
- отдельным блоком идут подробно описанные тестовые сценарии
- автоматизируйте поднятие окружения для запуска вашей программы
- Весь реализованный ранее функционал работает как раньше, только в контексте конкретного пользователя ✔
- У кого выражения хранились в памяти - переводим хранение в СУБД ✔
- У кого общение вычислителя и сервера вычислений было реализовано с помощью HTTP - переводим взаимодействие на GRPC ✗
- Покрытие проекта модульными тестами ✔
- Покрытие проекта интеграционными тестами ✔
Пожалуйста, если умеете делать Docker контейнер, помогите исправить файлик, у меня не вышло, я готов заплатить, напишите мне.
Способ дедовский:
- Склонировать проект или скачать
- Установить PostgreSQL
- Поменять в config.json данные о PostgreSQL(и другие если хотите)
- Установить все зависимости из go.mod
go mod downloadgo mod tidy - Включить сервер PostgreSQL
- Запустить файл main.go
Сначала RemoveAllSpaces убирает пробелы в выражении
- HasDoubleSymbol проверяет на двойной символ
- IsValidParentheses проверяет скобочную последовательность
- HasDivizionByZero проверяет есть ли деление на ноль
- HasValidCharacters проверяет на допустимые символы
- ContainsCorrectFloatPoint проверяет на точку в правильном месте(должно быть в числе float)
- HasAtLeastOneExpression проверяет на хотя бы одно выражение число оператор число
- ExpressionStartsWithNumber проверяет - первым ли идёт число или скобка в выражении
- Делаем постфиксную запись выражения
- Ищем выражения вида
24+(число число оператор) или ищем выражения вида2 + 2 +(число оператор число оператор(операторы одинаковые)) - Отправляем субвыражения на горутины(агенты)
- Подставляем обратно в постфиксную запись наши субвыражения
- Повторяем пока не останется одно число
Есть файл Postman
Запросы делал через Postman
http://localhost:8080/register- метод POST и Body такое(регистрация):
{
"username": "someuser@gmail.com",
"password": "Qwerty_123"
}http://localhost:8080/login- метод POST и Body такое же как в register(вход)
Дает JWT токен, который впоследствии надо вписывать во все запросы(засовывать в Header так: "Authorization": "Bearer <JWT токен>"), написанные ниже
http://localhost:8080/expression- метод POST и Body например такое(отправляем выражение на обработку):
{
"expression": "(2+2)*2"
}http://localhost:8080/expressionметод GET - получаем все выраженияhttp://localhost:8080/expression/1метод GET - получаем выражение с id = 1http://localhost:8080/operationметод GET - получаем все операции(длительность операции)http://localhost:8080/operationметод PUT - обновляем операцию тут Body будет например такое:
{
"OperationKind": "addition",
"durationInMilliSecond": 20
}http://localhost:8080/agentметод PUT - добавляем одного агента-
http://localhost:8080/agentметод DELETE - удаляем одного агента
http://localhost:8080/agentsметод GET - получаем всех агентов
У нас читается конфиг с файла config.json, инициализируется БД, chi роутер, выполняются непосчитанные выражения и привязываются паттерны. По вызванному паттерну есть хендлер в котором обрабатывается запрос и идет работа с БД, создаются таски с выражениями и длительностью операций. Всё обрабатывается и возвращается ответ.
Используемые технологии:
chi, viper, pgx, slog, postgresql, docker(я пытался), JWT
По всем вопросам и не вопросам пишите в Telegram
Special thanks to this video

