Skip to content

About Test assignment for the Middle Python Developer position in Natural Intelligence

Notifications You must be signed in to change notification settings

mabredin/nat_intell_test_task

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Тестовое задание на позицию Middle Python developer

Задание

Разработать два микросервиса, взаимодействующие друг с другом для реализации API сервиса голосования. Общение между ними должно работать через GRPC.

1. Сервис на Python для базовой работы с криптовалютой ethereum

Должен иметь следующие grpc методы: 

  1. GetBalance - получение баланса по ethereum адресу.
  2. GetLatestBlock - получение информации по последнему блоку. Метод должен вернуть номер блока, количество транзакций, сложность блока и время создания.
  3. VerifyAddress - проверка адреса на валидность и то что он не является смарт контрактом.

2. Сервис на Python в виде REST API

Необходимые сущности:

  • Proposal - предложение за которое могут голосовать пользователи. Должно содержать следующие данные: заголовок предложения, описание предложения.
  • Vote - голос пользователя, можно голосовать только за или против какого-либо Proposal. Должен содержать следующие данные: голос (за или против), баланс пользователя на момент голоса, номер текущего блока на момент голоса.
  • User - пользователь, который может голосовать. Должен содержать следующие данные: адрес пользователя в сети Эфир, номер блока на момент регистрации пользователя.
  • Admin - пользователь с правами на редактирование Proposal. В остальном аналогичен обычному пользователю.

Необходимые методы:

  1. Create Proposal - создание Proposal (доступно только Admin).
  2. Update Proposal - редактирование данных Proposal (доступно только Admin), недоступно если за Proposal уже голосовали.
  3. Delete Proposal - удаление Proposal (доступно только Admin), недоступно если за Proposal уже голосовали.
  4. Get Proposals - получение всех Proposal.
  5. Register User - регистрация нового пользователя. На вход подается адрес, метод должен проверять адрес на валидность с помощью метода VerifyAddress 1-го сервиса, а также записывать текущий блок в сети на момент регистрации (использовать метод GetLatestBlock 1-го сервиса).
  6. Create Vote - запись голоса пользователя за какое-либо предложение. Голос пользователя учитывается, только если его баланс на момент голосования больше 0 (использовать метод GetBalance 1-го сервиса), в противном случае необходимо выдать ошибку. Баланс пользователя и номер текущего блока в сети необходимо записать вместе с голосом.
  7. Get Votes - получение суммарной информации о голосовании за конкретное предложение (сумма балансов голосов за и сумма балансов голосов против).

Сервис должен реализовать все методы необходимые для системы голосования, для реализации некоторых методов использовать обращения при помощи gRPC к внешнему микросервису (1-ый сервис) для получения данных из блокчейн сети.

Результат выполнения

Реализовано 2 микросервиса и спроектирована база данных для первого микросервиса, которые общаются между собой через gRPC:

1. Сервис голосования (microservice1)

  • Реализован в виде REST API.
  • В конце приведено описание для пары основных методов
  • Остальные можно найти в Swagger документации после развертывания приложения по адресу host:port/docs. Там вы можете подробно ознакомиться со всеми методами и даже их пощупать. 2. Сервис для работы с ethereum (microservice2)
  • Служит для получения, обработки и передачи информации об ethereum.
  • Имеет следующие gRPC методы:
    • GetBalance получает адрес кошелька (address) и отдает его баланс (balance);
    • GetLatestBlock ничего не получает, отдает номер последнего блока (number) на момент выполнения, количество транзакций (count_transactions), сложность блока (difficulty) и время создания (time);
    • VerifyAddress получает адрес кошелька (address), проверяет его подлинность и отдает булевый ответ (is_verified); 3. База данных
  • Реализовано 3 сущности - Proposal, User, Vote.
  • Между сущностями Proposal и User существует связь Многие-ко-Многим через ассоциативную таблицу Vote.

Технологии

  • Сервис 1 разработан с использованием ЯП Python, фреймворков FastAPI для реализации API, SQLAlchemy для работы с базой данных, библиотека uvicorn для запуска сервера и др.
  • В качестве БД использовался PostgreSQL. Для обеспечения корректной связи FastAPI и PostgreSQL использовалась библиотека asyncopg.
  • Сервис 2 разработан с использованием ЯП Python, фреймворка web3 для работы с ethereum, библиотеки grpcio для реализации общения через gRPC и др.
  • Микросервисы и база данных обернуты в Docker-контейнеры и запускаются при помощи docker compose

Запуск

Локально

Приложение развертывается и запускается через docker. Для запуска приложения необходимо:

Скачать из проекта docker-compose.yml или сделать свой с данными из репозитория:

В нем заполнить следующие переменные окружения:

  • SECRET_KEY_TOKEN - для хешириваноя паролей пользователей. Его можно сгенерировать с помощью команды:
openssl rand -hex 32
  • INFURA_ENDPOINT - публичная нода для работы с ethereum
    Выполнить команду запуска контейнеров
docker compose up
  • Перейти по адресу 0.0.0.0:8000/docs. Это Swagger документация.
  • Необходимо создать пользователя и авторизоваться. Находим метод api_v1_auth_register и заполняем данные.
  • Далее ищем серый открый замок у любого из методов, нажимаем и вводим username и password.
  • Сервис готов. Балуйтесь :)

На удаленной машине

На удаленной машине алгоритм аналогичен. Изменится только адрес. Необходимо перейти на адрес удаленной машины. Порт 8000. Наример, я развернул проект на своем удаленном виртуальном сервере. Он доступен по адресу http://45.131.40.80:8000/docs.

Метода 1 микросервиса

Name Description
ENDPOINT: /api/v1/auth/register
METHOD: POST
PARAMETERS: None
INPUT VALUES: {
"username": "string",
"hashed_password": "string",
"email": "string",
"wallet_address": "string",
"is_superuser": false
}
OUTPUT VALUES: {
"username": "string",
"email": "string",
"wallet_address": "string",
"block_number": 0,
"is_superuser": false,
"is_active": true
}
ENDPOINT: /api/v1/proposals
METHOD: POST
PARAMETERS: None
INPUT VALUES: {
"title": "string",
"description": "string",
}
OUTPUT VALUES: {
"title": "string",
"description": "string",
}
ENDPOINT: /api/v1/votes/{proposal_id}
METHOD: POST
PARAMETERS: "proposal_id": "int"
INPUT VALUES: {
"is_like": "bool"
}
OUTPUT VALUES: {
"proposal_id": 0,
"user_id": 0,
"is_like": false,
"user_balance": "string",
}

Примечание

В коде есть парочка недоочетов, в дальнейшем необходимо провести локализацию текстов ошибок, привести ответы к единому стандартизированному виду и предусмотреть все возможные ошибки, связанные с действиями пользователей.

About

About Test assignment for the Middle Python Developer position in Natural Intelligence

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published