Skip to content

⚡Simple and efficient expression evaluator, written in Go

Notifications You must be signed in to change notification settings

neptship/calc-yandex-go

Repository files navigation

сalc-yandex-go

Cервис на Go для вычисления арифметических выражений. Сервис принимает математические выражения через POST-запросы и возвращает вычисленные результаты.

Функциональность

  • Асинхронное вычисление арифметических выражений
  • Поддержка базовых арифметических операций (+, -, *, /)
  • Поддержка скобок для управления порядком операций
  • Формат обмена данными JSON
  • Распределённое выполнение операций между агентами
  • История вычислений с подробной информацией
  • Веб-интерфейс для удобного использования
  • Обработка ошибок с соответствующими HTTP-кодами

Установка и запуск

Предварительные требования

  • Установленный Go (версия 1.20 или выше)
  • Node.js 18+ и npm (для фронтенда)
  • Docker и Docker Compose (для запуска через Docker)
  • Make (опционально, для упрощения запуска)

Запуск через Make

Для удобства запуска всех компонентов системы используйте команды Make:

# Клонирование репозитория
git clone https://github.com/neptship/calc-yandex-go
cd calc-yandex-go

# Установка всех зависимостей (Go модулей и npm пакетов)
make install

# Запуск всех компонентов (оркестратор, агент, фронтенд)
make run-all

Запуск через Docker

Проект поддерживает запуск через Docker и Docker Compose:

git clone https://github.com/neptship/calc-yandex-go
cd calc-yandex-go
docker-compose up

Ручной запуск

Клонирование репозитория и установка зависимостей

# Клонирование репозитория
git clone https://github.com/neptship/calc-yandex-go
cd calc-yandex-go

# Установка Go модулей
go mod tidy

# Установка npm пакетов
cd frontend
npm install
cd ..

Запуск оркестратора

go run cmd/orchestrator/main.go

Запуск агентов (В отдельном терминале)

go run cmd/agent/main.go

По умолчанию оркестратор запускается на порту 8080.

Запуск фронтенда

cd frontend
npm run dev

Веб-интерфейс будет доступен по адресу: http://localhost:3000

API Спецификация

flowchart LR
    A[Фронтенд Next.js] -->|Отправка выражения| B[Оркестратор Go]
    B -->|Задачи с указанным временем| C[Агенты Go]
    C -->|Результаты операций| B
    B -->|Итоговый ответ| A
Loading

POST /api/v1/calculate

Отправляет выражение на вычисление и возвращает идентификатор задачи.

Формат запроса:

{
    "expression": "2+2*2"
}

Успешный ответ (201 Created):

{
    "id": 1
}

Ответ при некорректном выражении (422 Unprocessable Entity):

{
    "error": "invalid expression"
}

Ответ при внутренней ошибке сервера (500 Internal Server Error):

{
    "error": "internal server error"
}

GET /api/v1/expressions/:id

Получает статус и результат вычисления по идентификатору.

Успешный ответ (200 OK), вычисление завершено:

{
    "expression": {
        "id": 1,
        "status": "completed",
        "result": 6
    }
}

Успешный ответ (200 OK), вычисление в процессе:

{
    "expression": {
        "id": 1,
        "status": "processing"
    }
}

Выражение не найдено (404 Not Found):

{
    "error": "Expression not found"
}

GET /api/v1/expressions

Получает список всех выражений и их статусов.

Успешный ответ (200 OK):

{
    "expressions": [
        {
            "id": 1,
            "status": "completed",
            "result": 6
        },
        {
            "id": 2,
            "status": "processing"
        }
    ]
}

GET /internal/task

Получает задачу для выполнения агентом.

Успешный ответ (200 OK):

{
    "task": {
        "id": 1,
        "arg1": 2,
        "arg2": 2,
        "operation": "+",
        "operation_time": 1000
    }
}

Ответ, если нет доступных задач (404 Not Found):

{
    "error": "No tasks available"
}

POST /internal/task

Отправляет результат выполнения задачи.

Формат запроса:

{
    "id": 1,
    "result": 4
}

Успешный ответ (200 OK):

{
    "success": true
}

Ответ, если задача не найдена (404 Not Found):

{
    "error": "Task not found"
}

Примеры использования

Успешные сценарии

Отправка выражения на вычисление

curl --location 'http://localhost:8080/api/v1/calculate' \
--header 'Content-Type: application/json' \
--data '{
    "expression": "2+2*2"
}'

Ответ:

{
    "id": 1
}

Отправка сложного выражения

curl --location 'http://localhost:8080/api/v1/calculate' \
--header 'Content-Type: application/json' \
--data '{
    "expression": "(70/7) * 10 /((3+2) * (3+7)) - 2"
}'

Ответ:

{
    "id": 2
}

Получение результата вычисления

curl --location 'http://localhost:8080/api/v1/expressions/1'

Ответ:

{
    "expression": {
        "id": 1,
        "status": "completed",
        "result": 6
    }
}

Получение списка всех выражений

curl --location 'http://localhost:8080/api/v1/expressions'

Ответ:

{
    "expressions": [
        {
            "id": 1,
            "status": "completed",
            "result": 6
        },
        {
            "id": 2,
            "status": "processing"
        }
    ]
}

Получение задачи агентом

curl --location 'http://localhost:8080/internal/task'

Ответ:

{
    "task": {
        "id": 3,
        "arg1": 3,
        "arg2": 5,
        "operation": "+",
        "operation_time": 1000
    }
}

Отправка результата задачи

curl --location 'http://localhost:8080/internal/task' \
--header 'Content-Type: application/json' \
--data '{
    "id": 3,
    "result": 8
}'

Ответ:

{
    "success": true
}

Обработка ошибок

Невалидный JSON при отправке выражения

curl --location 'http://localhost:8080/api/v1/calculate' \
--header 'Content-Type: application/json' \
--data 'not-valid-json'

Ответ:

{
    "error": "Invalid request format"
}

Некорректное выражение

curl --location 'http://localhost:8080/api/v1/calculate' \
--header 'Content-Type: application/json' \
--data '{
    "expression": "2+*2"
}'

Ответ:

{
    "error": "invalid expression"
}

Запрос несуществующего выражения

curl --location 'http://localhost:8080/api/v1/expressions/999'

Ответ:

{
    "error": "Expression not found"
}

Деление на ноль

curl --location 'http://localhost:8080/api/v1/calculate' \
--header 'Content-Type: application/json' \
--data '{
    "expression": "5/0"
}'

После проверки статуса выражения:

{
    "expression": {
        "id": 3,
        "status": "failed",
        "result": null
    }
}

Запрос задачи, когда нет доступных задач

curl --location 'http://localhost:8080/internal/task'

Ответ:

{
    "error": "No tasks available"
}

Некорректный запрос при отправке результата задачи

curl --location 'http://localhost:8080/internal/task' \
--header 'Content-Type: application/json' \
--data 'not-valid-json'

Ответ:

{
    "error": "Invalid request body"
}

Отправка результата для несуществующей задачи

curl --location 'http://localhost:8080/internal/task' \
--header 'Content-Type: application/json' \
--data '{
    "id": 999,
    "result": 42
}'

Ответ:

{
    "error": "Task not found"
}

Настройка

Система настраивается через переменные окружения:

  • PORT - порт для HTTP-сервера (по умолчанию 8080)
  • COMPUTING_POWER - количество параллельных вычислителей в агенте (по умолчанию 3)
  • TIME_ADDITION_MS - время выполнения сложения (по умолчанию 1000 мс)
  • TIME_SUBTRACTION_MS - время выполнения вычитания (по умолчанию 1000 мс)
  • TIME_MULTIPLICATIONS_MS - время выполнения умножения (по умолчанию 1500 мс)
  • TIME_DIVISIONS_MS - время выполнения деления (по умолчанию 2000 мс)

Ограничения

  • Поддерживаются только положительные целые числа
  • Использование унарного минуса или плюса приведет к некорректной работе
  • Поддерживаются только POST-запросы
  • Все нестандартные символы в выражении (буквы, спецсимволы) приведут к ошибке 422

Веб-интерфейс

Веб-интерфейс предоставляет следующие возможности:

  • Ввод арифметических выражений
  • Отображение прогресса вычислений в реальном времени
  • История вычислений с результатами
  • Просмотр подробной информации в JSON-формате
  • Очистка истории

Запуск тестов

# Запуск всех тестов
cd calc-yandex-go
make test

# или напрямую
go test ./... -v

Рекомендации по тестированию

  • Рекомендуется использовать Postman для тестирования API, так как с curl могут возникнуть проблемы
  • При использовании curl рекомендуется выполнять запросы через git bash терминал
  • Для тестирования асинхронных вычислений сделайте запрос, а затем периодически запрашивайте результат

Структура проекта

/calc-yandex-go/
├── cmd/                     # Точки входа для исполняемых файлов
│   ├── orchestrator/        # Оркестратор
│   └── agent/               # Агент
├── internal/                # Внутренние пакеты
│   ├── agent/               # Логика агента
│   ├── config/              # Конфигурация
│   ├── models/              # Модели данных
│   └── orchestrator/        # Логика оркестратора
├── pkg/                     # Переиспользуемые пакеты
│   └── calculation/         # Парсинг и вычисление выражений
├── frontend/                # Next.js фронтенд
└── docker-compose.yml       # Конфигурация Docker