https://github.com/mementomorri/micro_octo_handler
Микросевисное приложение обработки сообщений на основе архитектуры REST.
https://github.com/mementomorri/micro_octo_handler
fastapi fastapi-users jwt microservice python rest sqlite
Last synced: 8 months ago
JSON representation
Микросевисное приложение обработки сообщений на основе архитектуры REST.
- Host: GitHub
- URL: https://github.com/mementomorri/micro_octo_handler
- Owner: mementomorri
- License: gpl-3.0
- Created: 2024-03-19T20:00:33.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-04-03T12:49:13.000Z (almost 2 years ago)
- Last Synced: 2025-02-23T10:18:53.495Z (12 months ago)
- Topics: fastapi, fastapi-users, jwt, microservice, python, rest, sqlite
- Language: Python
- Homepage:
- Size: 2.09 MB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# micro_octo_handler
Микросевисное приложение обработки сообщений на основе архитектуры REST.
## Дословная формулировка т/з
Реализовать приложение, принимающее запросы на обработку через REST.
Сообщения обрабатываются двумя провайдерами:
- бесплатным
- и платным,
путем общения через REST.
По бесплатному провайдеру есть ограничение: он может принять какое-то количество запросов, затем блокирует обращения на определённый промежуток времени.
Возможно получить отказ в обслуживании формированием рабочего запроса на бесплатный сервис, однако правильнее обрабатывать количество отправленных запросов в сервис и сравнивать с доступным количеством.
При блокировке запросы следует отправлять в платный сервис. При доступности бесплатного сервиса следует переключиться на бесплатный, минимизируя использование платного провайдера.
При разработке иметь в виду, что приложение может работать на нескольких изолированных подах без использования общей памяти.
Необходимо наличие тестов.
## Интуиция
1. Поскольку подразумивается, что приложение может быть разделено на несколько подов, то имеет смысл реализовать микросервисную архитектуру. Приложение будет разделено на три микросервиса:
- бесплатный провайдер;
- платный провайдер;
- аутентификация пользователей.
2. По-умолчанию буду направлять клиента на бесплатный провайдер, если пороговое значение запросов превышено, то клиент будет перенаправлен на платный провайдер. Для имитации работы платного провайдера условно ограничу его использование по ключевому аттрибуту JWT токене.
3. Необходимо каким-то образом идентифицировать пользователя, поэтому добавлю идентификаю пользователя по стратегии JWT хранимых в куки файлах и изолирую пользователя от платного провайдера, если у него нет права доступа.
4. Наличие БД не является необходимым, поскольку по заданию не уточняется нужно ли хранить информацию об обработанных сообщениях и нужно ли её кэшировать. Обработка сообщений в провайдерах будет имитироваться через обработку переданной строки сообщения.
## Реализация
Реализовано два провайдера обработки сообщений `free_provider` для бесплатной обработки сообщений и `paid_provider` для платной соответственно. Также добавлен микросервис для аутентификации пользователей и обработки информации связанной с ними `user_microservice`. Перед обработкой сообщения пользователь направляется на микросервис аутентификации, получает JWT токен и получает доступ к провайдеру обработки сообщений. При поверхностном тестировании обработка сообщений и переключение между провайдерами работает корректно. Проверить это можно в ручную собрав `venv` через соответствующие файлы зависимостей в папке `requierements` или через сборку контейнера используя `Dockerfile` в соответствующих папках провайдеров и микросервиса аутентификации пользователей.
## Сборка и запуск
### Контейнеры
Можно сэимитировать разделение микросервисов на поды собрав каждый в отдельный докер контейнер. В папках `src/user_microservice`, `src/free_provider` и `src/paid_provider` имеются инструкции Dockerfile для сборки контейнера. Их можно собрать с помощью команд в комментариях к Dockerfile, а именно:
- `src/user_microservice/Dockerfile` - собираем и запускаем командой: ```docker build . --tag users_microservice && docker run -p 8000:8000 users_microservice```;
- `src/free_provider` - собираем и запускаем командой: ```docker build . --tag free_provider && docker run -p 2197:2197 free_provider```;
- `src/user_microservice/Dockerfile` - собираем и запускаем командой: ```docker build . --tag paid_provider && docker run -p 2198:2198 paid_provider```.
Каждый микросервис будет имееть соответствущий адес:
- http://0.0.0.0:8000 для микросервиса пользователей;
- http://0.0.0.0:2197 для бесплатного провайдера;
- http://0.0.0.0:2198 для платного провайдера.
Также можно заглянуть в сгенерированную документацию в разделе `/docs` каждого микросервиса.
### venv
1. Для быстрой сборки и запуска приложения в режиме отладки можно воспользоваться скриптом `build_and_deploy.sh`.
2. Либо собрать зависимости в ручную через файл зависимостей `dev.txt` из папки `requierements`, инициализировать виртуальную среду командой:
```shell
cd requirements; python -m venv venv; source venv/bin/activate; pip install -r dev.txt
```
и запустить сервисы через `uvicorn` из каждой папки, например `uvicorn microservice:app --reload --port=8000`
## Ручное тестирование
Сымитируем поведение пользователя взаимодействующего в нашим приложением через API. Сначала пользователю необходимо зарегистрироваться, при регистрации укажем выиышленную почту и пароль для пользователя:

После регистрации наш тестовый пользователь bob получит ответ в виде статус кода 201 и в ответ получит добавленные о нем данные.

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

Если всё прошло успешно, пользователь получит статус код 204.

И JWT токен в виде куки.

Теперь пользователь хочет воспользоваться бесплатным провайдером обработки сообщений, перейдем на адрес с бесплатным провайдером, введем значение токена и обрабатываемое сообщение.

В ответ пользователь получит статус код 200 и результат обработки запроса. В тестовом варианте это просто перевернутая строка.

Теперь сыметируем ситуацию, когда пользователь отправил ещё 9 сообщений и лимит бесплатных сообщений для него закончился `"free_messages_left": 0`.

Теперь наш пользователь, не имея доступа к платному провайдеру, хочет обработать ещё одно сообщение, обращается к бесплатному провайдеру и получает такой ответ со статус кодом 403.

Представим, что наш пользователь приобрел платную подписку и теперь его поле `paid_access` имеет значение `true`, снова обратившись к бесплатному провайдеру он увидит сообщение.

Теперь сымитируем ситуацию, когда пользователь зарегистрировался днём ранее и исчерпал запас песплатных сообщений, обращайте внимание на дату в поле `refresh_at` - 25.03 и тукущую дату - 26.03.

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

Если взглянуть в данные о пользователе, то видно, что дата следующей выдачи бесплатных сообщение и количество бесплатных сообщение обновилось.
