- Описание проекта
- Структура проекта
- Схема работы распределенного вычислителя
- Фронтенд: Веб-интерфейс
- Требования для запуска проекта
- Установка и запуск проекта
- Проверка работы приложения
- Взаимодействие с API: примеры запросов
- Логирование в проекте
- Тестирование
Этот проект представляет собой распределенную систему для вычисления арифметических выражений, состоящую из оркестратора и агента. Система позволяет обрабатывать сложные арифметические выражения, разбивая их на отдельные операции, которые могут выполняться параллельно на разных вычислительных узлах.
Система состоит из ключевых компонентов: Пользователя, Оркестратора и Агента.
Пользователь отправляет выражение на вычисление в Оркестратор и запрашивает результат. Оркестратор управляет процессом вычислений. Он разбирает выражение, создаёт задачи и распределяет их. Готовые к исполнению задачи — задачи, которые могут быть сразу отправлены Агенту. Зависимые задачи — задачи, выполнение которых зависит от результатов других операций. Выполненные задачи — хранилище результатов завершенных вычислений. Агент получает задачи от Оркестратора, выполняет вычисления и отправляет результаты обратно. Оркестратор действует как центральный контроллер, управляя очередностью вычислений и взаимодействуя с Агентом. Пользователь взаимодействует только с Оркестратором, который скрывает внутреннюю логику обработки выражений.
graph TD;
User["User"] -->|"POST /api/v1/calculate"| Orchestrator;
User -->|"GET /api/v1/expressions/:id"| Orchestrator;
Orchestrator["Orchestrator"] -->|"Parse Expression"| Parse;
Parse["Parse Expression"] -->|"Build Expression Tree"| BuildTree;
BuildTree["Build Expression Tree"] -->|"Generate Tasks"| GenerateTasks;
GenerateTasks["Generate Tasks"] -->|"Task Store"| TaskStore;
TaskStore["Task Store"] -->|"GET /internal/task"| Agent;
Agent["Agent"] -->|"Execute Task"| ExecuteTask;
ExecuteTask["Execute Task"] -->|"POST /internal/task"| Orchestrator;
Orchestrator -->|"Update Expression Status"| TaskStore;
classDef mainNode fill:#333,stroke:#ccc,stroke-width:2px,font-weight:bold,color:#fff;
classDef subNode fill:#222,stroke:#777,stroke-width:1px,font-weight:normal,color:#ddd;
class User,Orchestrator,Agent mainNode;
class Parse,BuildTree,GenerateTasks,TaskStore,ExecuteTask subNode;
calculate_project
├── README.md # Описание проекта и инструкции
├── .env # Конфигурация
├── frontend # Фронтенд
│ ├── index.html # Веб-страница с формой калькулятора
│ ├── style.css # Стили
│ ├── script.js # Логика работы фронтенда
│ └── server.go # Локальный HTTP-сервер для раздачи фронтенда
├── cmd # Исполняемые файлы
│ ├── agent # Код агента (вычислителя)
│ │ ├── main.go # Точка входа для агента
│ │ └── main_test.go # Тесты агента
│ └── orchestrator # Код оркестратора (сервера)
│ ├── main.go # Точка входа для оркестратора
│ └── main_test.go # Тесты оркестратора
├── internal # Внутренняя логика приложения
│ ├── api # API-слой
│ │ ├── handlers.go # Обработчики HTTP-запросов
│ │ ├── handlers_test.go # Тесты обработчиков
│ │ ├── models.go # Модели данных для API
│ │ └── server.go # Настройка и запуск HTTP-сервера
│ └── application # Бизнес-логика приложения
│ ├── application.go # Основная логика работы с выражениями и задачами
│ └── application_test.go # Тесты бизнес-логики
└── pkg # Публичные пакеты
└── calculation # Пакет для вычисления выражений
├── calc.go # Логика вычисления арифметических выражений
├── calc_test.go # Тесты вычислений
├── errors.go # Обработка ошибок
└── validation.go # Валидация выражений
1. Инициализация:
- Оркестратор:
- Загружает конфигурацию из переменных окружения (время выполнения операций, порт).
- Создает структуры данных для хранения выражений, задач (очереди
taskQueue
иdependentQueue
), и результатов задач (taskResults
). Использует мьютекс (sync.Mutex
) для синхронизации доступа к этим структурам. - Запускает HTTP-сервер, ожидающий запросы от пользователей и агентов.
- Агент:
- Загружает конфигурацию из переменных окружения (URL оркестратора, количество вычислительных потоков
COMPUTING_POWER
). - Создает пул горутин (воркеров), каждая из которых будет независимо запрашивать и выполнять задачи. Количество воркеров определяется переменной
COMPUTING_POWER
. - Каждый воркер в бесконечном цикле обращается к оркестратору.
- Загружает конфигурацию из переменных окружения (URL оркестратора, количество вычислительных потоков
2. Добавление выражения (от пользователя к оркестратору):
- Пользователь отправляет HTTP POST-запрос на
/api/v1/calculate
оркестратора с телом запроса, содержащим арифметическое выражение в строковом формате (например,{"expression": "2 + 2 * (3 - 1)"}
). - Оркестратор (в обработчике
HandleCalculate
):- Проверяет, что запрос является POST.
- Декодирует тело запроса в структуру
RequestAddExpression
. - Вызывает функцию
ValidateExpression
для проверки корректности выражения (допустимые символы, баланс скобок, не пустое). Если валидация не пройдена, возвращает HTTP-ответ с кодом 422 и описанием ошибки. - Вызывает функцию
application.ParseExpression
, передавая ей строку с выражением. ParseExpression
:- Токенизация: Разбивает входную строку на токены (числа, операторы, скобки) с помощью функции
calculation.Tokenize
. - Преобразование в постфиксную нотацию: Преобразует токены в постфиксную нотацию (обратную польскую запись) с помощью алгоритма сортировочной станции (функция
calculation.InfixToPostfix
). Если обнаружены ошибки (например, несоответствие скобок), возвращается ошибка. - Создание задач: Проходит по токенам в постфиксной записи.
- Если токен – число:
- Создает "задачу" (хотя фактически это уже вычисленное значение).
- Сохраняет значение в
taskResults
под уникальным ID задачи. - Помещает ID задачи в стек.
- Если токен – оператор:
- Извлекает из стека ID двух последних задач (операндов).
- Создает новую задачу (
Task
) со статусом "pending". - Заполняет поля
Operation
,OperationTime
(на основе переменных окружения). - Заполняет
ParentTasks
, указывая ID извлеченных из стека задач. - Проверяет, есть ли уже результаты для родительских задач в
taskResults
. Если есть, сразу заполняетArg1
иArg2
задачи. - Если оба аргумента (
Arg1
иArg2
) заполнены, помечает задачу как готовую (IsReady = true
) и добавляет ее в очередь готовых задачtaskQueue
. - Если хотя бы один аргумент не заполнен, добавляет задачу в очередь зависимых задач
dependentQueue
. - Добавляет ID созданной задачи в стек.
- Если токен – число:
- Создает объект
Expression
, сохраняет в него исходное выражение, список созданных задач и присваивает ему статус "pending". - Сохраняет
Expression
в мапеexpressions
по уникальному ID выражения. - Возвращает ID выражения в обработчик
HandleCalculate
.
- Токенизация: Разбивает входную строку на токены (числа, операторы, скобки) с помощью функции
- Обработчик
HandleCalculate
возвращает пользователю HTTP-ответ с кодом 201 и телом, содержащим ID выражения (например,{"id": 123}
).
3. Выполнение задач (агент запрашивает задачу у оркестратора):
- Агент (внутри горутины-воркера) отправляет HTTP GET-запрос на
/internal/task
оркестратора. - Оркестратор (в обработчике
HandleGetTask
):- Вызывает функцию
application.GetNextTask
. GetNextTask
:- Проверяет, есть ли задачи в очереди
taskQueue
. - Если очередь пуста, возвращает
nil, nil
. - Если есть готовая задача, извлекает её из очереди
taskQueue
и возвращает.
- Проверяет, есть ли задачи в очереди
- Если
GetNextTask
вернулаnil
, обработчикHandleGetTask
возвращает агенту HTTP-ответ с кодом 404. - Если задача получена, обработчик
HandleGetTask
формирует ответ (ResponseGetTask
), содержащий информацию о задаче (ID, операцию, аргументы, время выполнения), и отправляет его агенту с кодом 200.
- Вызывает функцию
4. Выполнение задачи агентом:
- Агент (внутри горутины-воркера):
- Получает HTTP-ответ от оркестратора.
- Декодирует тело ответа в структуру
Task
. - Имитирует выполнение задачи, ожидая указанное в
OperationTime
время (используяtime.Sleep
). - Вызывает функцию
performOperation
, передавая ей аргументы и операцию из задачи. performOperation
:- Выполняет математическую операцию (+, -, *, /) над аргументами.
- Проверяет деление на ноль.
- Возвращает результат или ошибку.
- Формирует тело запроса (
RequestPostTask
), содержащее ID задачи и результат вычисления. - Отправляет HTTP POST-запрос на
/internal/task
оркестратора с результатом.
5. Прием результата (оркестратор получает результат от агента):
-
Оркестратор (в обработчике
HandlePostTask
):- Декодирует тело запроса в структуру
RequestPostTask
. - Проверяет наличие ID задачи.
- Вызывает функцию
application.CompleteTask
, передавая ей ID задачи и результат. CompleteTask
:- Сохраняет результат выполнения задачи в
taskResults
по ID задачи. - Ищет задачу в списке задач всех выражений (
expressions
). - Если задача найдена, обновляет её статус на "completed" и сохраняет результат.
- Проверяет, завершены ли все задачи в выражении. Если да, вычисляет итоговый результат выражения (результат последней выполненной задачи) и устанавливает статус выражения в "completed".
- Обновляет очередь зависимых задач (
dependentQueue
):- Проходит по всем задачам в
dependentQueue
. - Для каждой задачи проверяет, выполнены ли все её родительские задачи (проверяет наличие результатов в
taskResults
). - Если все родительские задачи выполнены, подставляет их результаты в
Arg1
иArg2
текущей задачи, помечает задачу как готовую (IsReady = true
) и перемещает её изdependentQueue
вtaskQueue
. - Задачи, для которых не все родительские задачи выполнены, остаются в
dependentQueue
.
- Проходит по всем задачам в
- Если задача не найдена, возвращает ошибку.
- Сохраняет результат выполнения задачи в
- Обработчик
HandlePostTask
возвращает агенту HTTP-ответ с кодом 200.
- Декодирует тело запроса в структуру
-
Оркестратор (в обработчике
HandleGetExpressionByID
):- Извлекает ID выражения из URL.
- Вызывает функцию
application.GetExpressionByID
, передавая ей ID. GetExpressionByID
:- Ищет выражение в мапе
expressions
по ID. - Если выражение не найдено, возвращает ошибку "expression not found".
- Если выражение найдено:
- Проверяет, все ли задачи в выражении выполнены.
- Если не все задачи выполнены, возвращает выражение с текущим статусом ("pending").
- Если все задачи выполнены, но статус выражения еще "pending", обновляет статус на "completed", устанавливает результат выражения (результат последней выполненной задачи) и возвращает обновленное выражение.
- Ищет выражение в мапе
- Обработчик
HandleGetExpressionByID
:- Если
GetExpressionByID
вернула ошибку "not found", возвращает пользователю HTTP-ответ с кодом 404. - Если произошла другая ошибка, возвращает 500.
- Если выражение найдено, формирует ответ (
GetExpressionResponse
), содержащий ID, статус и результат выражения, и отправляет его пользователю с кодом 200.
- Если
7. Получение списка выражений (от пользователя к оркестратору):
- Пользователь отправляет HTTP GET-запрос на
/api/v1/expressions
оркестратора. - Оркестратор (в обработчике
HandleExpressions
):- Вызывает функцию
application.GetAllExpressions
. GetAllExpressions
:- Возвращает мапу
expressions
со всеми выражениями.
- Возвращает мапу
- Обработчик
HandleExpressions
:- Формирует ответ (
ResponseGetExpressions
), содержащий список всех выражений (ID, статус, результат), и отправляет его пользователю с кодом 200.
- Формирует ответ (
- Вызывает функцию
Ключевые моменты и структуры данных:
- *
expressions
(map[int]Expression): Хранит все выражения, добавленные в систему. Ключ – ID выражения, значение – указатель на структуруExpression
. taskToExpression
(map[int]int): Отображает ID задачи на ID выражения, которому она принадлежит.- *
taskQueue
([]Task): Очередь готовых к выполнению задач. Задачи попадают сюда, если все их зависимости (родительские задачи) уже выполнены. - *
dependentQueue
([]Task): Очередь задач, которые ожидают выполнения своих родительских задач. Как только родительские задачи выполняются, зависимые задачи перемещаются вtaskQueue
. taskResults
(map[int]float64): Хранит результаты выполненных задач. Ключ – ID задачи, значение – результат (число с плавающей точкой).sync.Mutex
: Используется для синхронизации доступа к общим ресурсам (мапам и очередям) из разных горутин (обработчиков HTTP-запросов).- Постфиксная нотация: Входное выражение преобразуется в постфиксную нотацию (обратную польскую запись) для упрощения вычислений и однозначного определения порядка операций.
- Имитация длительных вычислений: Агент использует
time.Sleep
с длительностью, заданной в переменных окружения (TIME_..._MS
), чтобы имитировать реальные вычислительные затраты.
Проект включает простой веб-интерфейс, который позволяет:
- Ввести математическое выражение.
- Отправить его на сервер для вычисления.
- Получить и отобразить результат.
Перед запуском проекта убедитесь, что на вашем компьютере установлены:
- Go 1.18+ (для разработки и запуска проекта)
- Git (для клонирования репозитория)
- curl или Postman (для тестирования API)
Проект использует следующие внешние зависимости:
- github.com/joho/godotenv - для загрузки переменных окружения из файла .env
- Клонируйте репозиторий на свой компьютер с GitHub с помощью команды:
git clone https://github.com/StarwinM/go_final_sprint2
- Перейдите в каталог проекта
cd go_final_sprint2
- Установите все необходимые зависимости
go mod tidy
- Настройка переменных окружения
Проект уже содержит файл .env со следующими настройками:
TIME_ADDITION_MS=5000
# Время выполнения операции сложения (мс). Это время задержки, которое будет искусственно добавлено для имитации вычислительной нагрузки при выполнении операции сложения.TIME_SUBTRACTION_MS=7000
# Время выполнения операции вычитания (мс). Задержка для операции вычитания.TIME_MULTIPLICATIONS_MS=10000
# Время выполнения операции умножения (мс). Задержка для операции умножения.TIME_DIVISIONS_MS=15000
# Время выполнения операции деления (мс). Задержка для операции деления.PORT=8080
# Порт для запуска оркестратора. По умолчанию оркестратор будет слушать на порту 8080.ORCHESTRATOR_URL=http://localhost:%s
# URL оркестратора для агентов. Этот параметр используется для подключения агентов к оркестратору.COMPUTING_POWER=5
# Количество вычислительных потоков для агента. Указывает, сколько агентов будет одновременно выполнять вычисления.
При необходимости вы можете изменить эти значения под свои требования.
- Запуск оркестратора
go run cmd/orchestrator/main.go
После запуска оркестратор будет слушать на указанном в .env порту (по умолчанию 8080). В консоли появится сообщение:
Starting server on port :8080...
После того как сервер успешно запущен, он готов к приему запросов.
- Запуск агента
Откройте новое окно терминала и выполните:
go run cmd/agent/main.go
После запуска агент выведет сообщение:
Agent started with computing power: 5
Worker 1 started and waiting for tasks...
Worker 2 started and waiting for tasks...
Worker 3 started and waiting for tasks...
Worker 4 started and waiting for tasks...
Worker 5 started and waiting for tasks...
Проверку работы системы можно проверить несколькими способами:
Откройте файл frontend/index.html
в браузере или запустите локальный сервер в новом окне терминала:
cd frontend
go run server.go
Перейдите в браузере по адресу http://localhost:8081.
Веб-интерфейс позволяет ввести арифметическое выражение, отправить его на вычисление и увидеть результат.
!!! Длительность вычислений
Так как вычисления выполняются "очень-очень" долго, согласно описанию задачи, пользователю следует учитывать, что статус "Вычисляется..." может оставаться активным в течение продолжительного времени.
Это происходит потому что агент выполняет операции с задержками, которые задаются в файле .env
. По умолчанию время выполнения операций следующее:
TIME_ADDITION_MS=5000 # Сложение: 5 секунд
TIME_SUBTRACTION_MS=7000 # Вычитание: 7 секунд
TIME_MULTIPLICATIONS_MS=10000 # Умножение: 10 секунд
TIME_DIVISIONS_MS=15000 # Деление: 15 секунд
Что означает, что сложные выражения, содержащие много операций, могут выполняться десятки секунд.
Фронтенд запрашивает результат выражения каждые 3 секунды, используя 30 попыток, таким образом, браузер будет ожидать до 90 секунд, прежде чем сообщить пользователю, что результат не получен.
Если вы не получили результат, используя веб-интерфейс, проверьте, не слишком ли сложное выражение. Если выражение содержит много операций, оно может выполняться дольше 90 секунд.
Это можно сделать в терминале с помощью команды curl или в Postman – удобном графическом инструменте для работы с API. Нужно создать новый запрос, выбрать метод (GET/POST) и передавать данные в формате JSON.
Ниже рассмотрим примеры запросов с помощью команды curl.
Откройте новое окно терминала и выполните запросы:
Пример запроса:
curl -s -i --location 'http://localhost:8080/api/v1/calculate' \
--header 'Content-Type: application/json' \
--data '{
"expression": "2+2*3"
}'
Пример ответа:
HTTP/1.1 201 Created
Content-Length: 9
Content-Type: text/plain; charset=utf-8
{"id":4}
Возможные коды ответа:
Код | Описание |
---|---|
201 Created | Выражение принято для вычисления. Ответ содержит ID выражения. |
400 Bad Request | Отсутствует поле expression в теле запроса. |
422 Unprocessable Entity | Некорректные данные (например, "expression": "2++2" ). |
500 Internal Server Error | Ошибка на стороне сервера. |
Пример запроса:
curl -s -i --location 'http://localhost:8080/api/v1/expressions'
Пример ответа:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 415
{
"expressions": [
{"id": 4, "status": "pending", "result": 0},
{"id": 5, "status": "completed", "result": 0},
{"id": 9, "status": "completed", "result": -5.999999998},
{"id": 3, "status": "completed", "result": 2.6666666666666665}
]
}
Код | Описание |
---|---|
200 OK | Успешно получен список выражений. |
500 Internal Server Error | Ошибка на стороне сервера |
Пример запроса:
curl -s -i --location 'http://localhost:8080/api/v1/expressions/5'
Пример ответа:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 56
{"expression":{"id":5,"status":"completed","result":0}}
Код | Описание |
---|---|
200 OK | Успешно получено выражение. |
404 Not Found | Выражение с указанным идентификатором не найдено. |
500 Internal Server Error | Ошибка на стороне сервера. |
Для тестирования этого endpoint завершите работу агента, оставив запущенным только оркестратор. Затем отправьте запрос на выполнение выражения, чтобы оркестратор добавил его в очередь задач.
Пример запроса:
curl -s -i --location 'http://localhost:8080/api/v1/calculate' \
--header 'Content-Type: application/json' \
--data '{
"expression": "2+8/4"
}'
Затем, получив ответ с успешным выполнением добавления выражения на вычисление:
HTTP/1.1 201 Created
Date: Tue, 04 Mar 2025 10:39:28 GMT
Content-Length: 9
Content-Type: text/plain; charset=utf-8
{"id":1}
запустите запрос на получение задачи:
curl -s -i --location 'http://localhost:8080/internal/task'
Если ранее был отправлен запрос оркестратору на выполнение вычислений, но задача еще не была обработана, оркестратор вернет следующую задачу из очереди для выполнения.
Пример ответа:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 75
{"task":{"id":4,"arg1":8,"arg2":4,"operation":"/","operation_time":15000}}
Если в системе нет ожидающих выполнения задач — либо все выражения уже вычислены, либо запросы на их выполнение не отправлялись — оркестратор вернет ответ:
HTTP/1.1 404 Not Found
Content-Length: 0
Код | Описание |
---|---|
200 OK | Успешно получена задача. |
404 Not Found | Нет доступных задач. |
500 Internal Server Error | Ошибка на стороне сервера. |
Для проверки endpoint запомните id задачи из предыдущего ответа, например "id":4, и введите запрос с этим id
Пример запроса:
curl -s -i --location 'localhost:8080/internal/task' --header 'Content-Type: application/json' --data '{
"id": 4,
"result": 2.5
}'
Пример ответа:
HTTP/1.1 200 OK
Date: Tue, 04 Mar 2025 11:04:49 GMT
Content-Length: 0
Если введен номер несуществующей задачи, будет получен ответ
curl -s -i --location 'localhost:8080/internal/task' --header 'Content-Type: application/json' --data '{
"id": 47,
"result": 2.5
}'
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Tue, 04 Mar 2025 11:05:50 GMT
Content-Length: 26
task with ID 47 not found
Другие примеры невалидного id задачи:
curl -s -i --location 'localhost:8080/internal/task' --header 'Content-Type: application/json' --data '{
"id": а,
"result": 2.5
}'
HTTP/1.1 422 Unprocessable Entity
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Tue, 04 Mar 2025 11:07:17 GMT
Content-Length: 21
Invalid request body
Код | Описание |
---|---|
200 OK | Успешно записан результат. |
404 Not Found | Нет такой задачи. |
422 Unprocessable Entity | Невалидные данные в запросе, например: отсутствует поле id или result , id содержит некорректное значение (не число), result имеет неверный формат. |
500 Internal Server Error | Ошибка на стороне сервера. |
Для отладки и мониторинга работы системы в проекте используется логирование событий. Логи позволяют отслеживать процесс вычисления выражений, взаимодействие между оркестратором и агентами, а также выявлять возможные ошибки.
Каждое сообщение в логах содержит:
- Временную метку (в формате YYYY/MM/DD HH:MM:SS).
- Источник события (например, HandleCalculate, ParseExpression, CompleteTask).
- Описание действия (что произошло, какие данные обработаны).
Пример логов работы оркестратора:
2025/03/04 14:00:13 HandleCalculate: Received request
2025/03/04 14:00:13 ValidateExpression: Validating expression: 2+8/4
2025/03/04 14:00:13 ParseExpression: Processing expression: 2+8/4
2025/03/04 14:00:13 Tokenize: Final tokens: [2 + 8 / 4]
2025/03/04 14:00:13 InfixToPostfix: Final postfix expression: [2 8 4 / +]
2025/03/04 14:00:13 ParseExpression: Created task for number 2 with ID 1
2025/03/04 14:00:13 GetNextTask: Issued task ID 4 to agent
2025/03/04 14:00:13 HandlePostTask: Successfully completed task ID 4
Пример логов работы агента:
2025/03/04 13:59:11 ORCHESTRATOR_URL: http://localhost:8080
2025/03/04 13:59:11 Agent started with computing power: 5
2025/03/04 13:59:11 Worker 1 started and waiting for tasks...
2025/03/04 13:59:21 Worker 1 received task: ID=4, Operation=/, Arg1=8.00, Arg2=4.00, OperationTime=15000ms
2025/03/04 13:59:36 Worker 1 successfully sent result for task 4 to http://localhost:8080
Оркестратор логирует следующие события:
- Приём выражений (HandleCalculate).
- Разбор и токенизация выражения (ParseExpression, Tokenize, InfixToPostfix).
- Cоздание и обработка задач (taskQueue, dependentQueue).
- Выдача задач агентам (HandleGetTask).
- Приём результатов от агентов (HandlePostTask, CompleteTask).
- Обнаруженные ошибки (например, task with ID 47 not found).
Агент логирует:
- Запуск и настройку (ORCHESTRATOR_URL, COMPUTING_POWER).
- Запросы задач у оркестратора (GET /internal/task).
- Получение задачи (Worker 1 received task: ID=4, Operation=/, Arg1=8.00, Arg2=4.00).
- Выполнение вычисления (Sleeping for 15000ms to simulate computation).
- Отправку результата обратно оркестратору (POST /internal/task).
Благодаря логированию можно отследить работу системы на всех этапах – от разбора выражений и создания задач до их выполнения агентами и возврата результата. Логи позволяют: прослеживать путь вычислений, видеть, как выражение разбивается на задачи, понимать, какие задачи выполняются в данный момент, и нет ли зависших вычислений, диагностировать ошибки в передаче данных между оркестратором и агентами, контролировать время выполнения операций, чтобы оптимизировать систему.
Для написания тестов используется стандартная библиотека Go testing, которая предоставляет базовые функции для написания, выполнения и проверки результатов тестов.
Для проверки правильности работы кода можно использовать стандартный инструмент Go для тестирования — go test
.
- Перейдите в корневую папку проекта
cd calculate_project
- Запуск всех тестов Чтобы запустить тесты, выполните следующую команду:
go test ./...
Эта команда выполнит все тесты во всех пакетах проекта, включая модули оркестратора, агентов, логики вычислений, а также API.
Пример ответа:
ok calculator_project/cmd/agent 1.049s
ok calculator_project/cmd/orchestrator 0.585s
ok calculator_project/internal/api 0.620s
ok calculator_project/internal/application 0.473s
ok calculator_project/pkg/calculation 0.262s
- Запуск тестов для конкретного пакета Если вам нужно запустить тесты только для конкретного пакета, например, для пакета с логикой вычислений, используйте команду:
go test ./pkg/calculation
Эта команда выполнит тесты только для пакета pkg/calculation.
- Запуск тестов с выводом подробной информации Если нужно увидеть детальный вывод тестов, добавьте флаг -v:
go test -v ./...
Тесты в проекте проверяют правильность работы функций и алгоритмов, таких как:
Корректность вычислений арифметических выражений:
Проверка базовых операций (+, -, *, /).
Обработка операторного приоритета (2 + 2 * 2 → 6).
Проверка работы со скобками ((3 + 5) * 2 → 16).
Обработка ошибок:
Деление на ноль (1 / 0 → Ошибка).
Некорректные выражения (2 + * 2 → Ошибка 422 "invalid expression").
Работа очереди задач в оркестраторе:
Проверка постановки задач в очередь (taskQueue).
Проверка зависимых задач (dependentQueue).
Проверка обработки готовых задач (taskResults).
Работа с агентами:
Получение задач агентами (GET /internal/task).
Корректное выполнение вычислений с задержкой (time.Sleep).
Отправка результатов (POST /internal/task).
API оркестратора:
Добавление выражений (POST /api/v1/calculate).
Запрос списка выражений (GET /api/v1/expressions).
Запрос выражения по ID (GET /api/v1/expressions/{id}).