10000 GitHub - helenochcka/Calculator: Backend for concurrent instruction calculations
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

helenochcka/Calculator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Описание

Данный проект - задание в рамках дисциплины по backend разработке, которое было следующим:

Вычислятор

Требуется реализовать приложение, принимающее на вход список инструкций. Существуют два вида инструкций:

  1. calc: вычислить арифметическую операцию (умножение, сложение, вычитание) над двумя сущностями и сохранить результат в переменную. Сущность может быть либо литерал типа int64, либо имя переменной. В одну и ту же переменную записывать результат можно только один раз.
  2. print: вывести значение указанной переменной, например, x = 5 Считаем, что каждая арифметическая операция из инструкций вычисляется долго, например 50ms. Требуется наиболее быстро вычислять результаты списка инструкций, т.е. выводить требуемые переменные.

Пример

input

[
 { "type": "calc", "op": "+", "var": "x",        "left": 10,   "right": 2    },
 { "type": "calc", "op": "*", "var": "y",        "left": "x",  "right": 5    },
 { "type": "calc", "op": "-", "var": "q",        "left": "y",  "right": 20   },
 { "type": "calc", "op": "+", "var": "unusedA",  "left": "y",  "right": 100  },
 { "type": "calc", "op": "*", "var": "unusedB",  "left": "unusedA", "right": 2 },
 { "type": "print",             "var": "q"                        },
 { "type": "calc", "op": "-", "var": "z",        "left": "x",  "right": 15   },
 { "type": "print",             "var": "z"                        },
 { "type": "calc", "op": "+", "var": "ignoreC",  "left": "z",  "right": "y"  },
 { "type": "print",             "var": "x"                        }
]

output

{ "items":
[
 {"var": "q","value": 40},
 {"var": "z","value": -3},
 {"var": "x","value": 12}
]
}

Приложение реализовано на Go с использованием брокера сообщений RabbitMQ и разделено на два сервиса - Executor и Arithmetic.

Так как задание подразумевало, что математические операции выполняются долго, будто это запрос в другой сервис, логика вычислений была на самом деле вынесена в отдельный сервис (для наглядности).

Executor - основной сервис, на который поступают запросы со списком инструкций от пользователей, а Arithmetic занимается математическими вычислениями.

Executor обрабатывает инструкции, отправляет запросы на Arithmetic (через gRPC), затем ждет ответы в брокере сообщений и обрабатывает эти ответы. Arithmetic помимо самих вычислений также отправляет их результаты в брокер сообщений.

Благодаря тому, что логика вычислений вынесена в отдельный сервис, есть возможность использовать брокер сообщений для асинхронной обработки результатов, что упростит логику в основном сервисе, избавив от необходимости каких-либо элементов синхронизации, а также позволит независимо масштабировать арифметический сервис и значительно увеличить количество инструкций в контексте одного запроса на основной сервис.

Архитектура кода

Архитектура кода обоих сервисов - слоистая. То есть в центре — бизнес-логика со всеми её сущностями, которые занимаются прикладными задачами. К бизнес-логике относятся use cases (код, который выполняет какой-либо бизнес-процесс, в качестве действий использует атомарные методы сервисов) и services (группа методов, которые группируются в сервисы по смысловой нагрузке и необходимы для изоляции сценария от внешних зависимостей). Вокруг бизнес-логики - драйверы, которые могут исп 642F ользоваться как для вызова бизнес-логики (handlers).

internal
├── arithmetic
│   ├── handlers    # HTTP-обработчики
│   ├── services    # Слой-посредник между бизнес-логикой и инфраструктурой
│   ├── use_cases   # Сценарии использования (application logic)
│   └── entities.go # Бизнес-сущности
├── executor
│   ├── dto         # Объекты передачи данных между слоями
│   ├── handlers    # HTTP-обработчики
│   ├── services    # Слой-посредник между бизнес-логикой и инфраструктурой
│   ├── use_cases   # Сценарии использования (application logic)
│   ├── entities.go # Бизнес-сущности
│   └── errors.go   # Доменные ошибки

На данный момент реализовано 2 хэндлера для сервиса Executor - grpc и rest. rest реализован с помощью фреймворка gin. Хэндлеры занимаются первичной валидацией инструкций и их распределением по типам для дальнейшей передачи в сценарий. Также хэндлеры кладут id запроса в контекст (так как он выступает именем очереди в брокере) и маппят доменные ошибки к интерфейсным.

В качестве API документации у rest - Swagger, а у grpc - его proto файл.

Также бизнес логика обоих сервисов покрыта unit тестами с использованием GoMock.

Запуск

Для приложения написан docker-compose.yml, а все параметры конфигурации задаются через config.yaml.

Для запуска проекта, включая RabbitMQ, можно выполнить одну команду:

docker-compose up -d

Swagger-документация

С дефолтным config.yaml Swagger UI доступен по адресу: http://localhost:8080/swagger/index.html#

About

Backend for concurrent instruction calculations

Resources

Stars

Watchers

Forks

0