Проектная работа

Проектная работа
Контекст
Продукт FoxReader находится в проде, имеет витрины в виде мобильного приложения и веб-версии. Сейчас в FoxReader можно потреблять контент в виде электронных книг, которые доступны во встроенной библиотеке, предоставляемой этим сервисом.

Монетизация сервиса осуществляется за счет продажи ежемесячных подписок для доступа к библиотеке контента.

Для увеличения аудитории и увеличение среднего чека появилась идея добавить новый тип контента - аудио-книги. На них предполагается доп подписка, которая может идти, как отдельно, так и вместе с основной. Во втором случае на доп подписку будет скидка.

Текущий поставщик электронных книг заявляет, что готов предоставлять и аудио-книги, но ему нужны требования. Сейчас они у поставщика просто есть в наличии и хранятся на дисках (в таком виде их предоставляют издательства)
Дизайн
Состояние as-is:

Технические вводные
Архитектура
Архитектура системы представлена в формате контейнерной диаграммы (С4 model, level 2):
Описание
Алгоритм загрузки данных в приложение
Ниже представлен алгоритм, описывающий процесс загрузки данных по книгам в приложение/web-site:
  • Integration Service по заданному ранее расписанию (например, в 23:59 по Мск):
  1. Вызывает метод 1. Метод загрузки каталога книг для загрузки массива книг
  2. По id сранивает полученные книги с книгами, ранее сохраненными в БД
  • если книга отсутствует в списке полученных, то в БД данная книга отмечается "depricated" и файл этой книги удаляется из хранилища
  • если книга присуттствует в БД, то переходим на шаг 3
3. Добавляет книги в БД
4. Вызывает метод 2. Метод загрузка контента: файлы книг //общий для текста и аудио для загрузки файла книги и сохраняет ее в хранилище данных. Шаг повторяется N раз, где N - кол-во новых книг.
  • Content Storage отправляет уведомления в CMS, если:
  • Не хватает обязательных полей, необходимых для отображения карточки в приложении (картинка и/или описание)
  • Если есть удаленные книги
[проходит время]
  • Content Manager донастраивает карточки книг
  • CMS отправляет изменения в Content Storage
[проходит время]
  • Пользователь запускает приложение/открывает веб-сайт
  • Приложение/веб-сайт запрашивает данные по карточкам книг у BE, используя метод 1. Метод загрузки контента для карточки книг
  • BE запрашивает данные у CMS
  • CMS обращается в Content Storage
  • Content Storage формирует ответ и возвращает данные CMS
  • CMS возвращается данные BE
  • BE возвращает каталог книг мобильному приложению/веб-сайту, используя метод 1. Метод загрузки контента для карточки книг
[проходит время]
  • Пользователь выбирает книгу и нажимает кнопку "Загрузить"
  • Мобильное приложение/веб-сайт загружает по ссылке книгу, обащаясь в Content Storage - 2. Метод загрузка контента: файлы книг //общий для текста и аудио
Вводные по методам
Клиент-серверное взаимодействие
1. Метод загрузки контента для карточки книги

Запрос
Параметры
Название
Тип параметра
Обязательность
Описание
Authorization
HEADERS

Bearer <access_token>


Access_token пользователя, который FE получает от BE после авторизации его в системе FoxReader

<version_api>
PATH

Версия API

Текущее значение - v1

content
PATH

Каталог

<content_id>
PATH

Идентификатор запрашиваемой книги

Ответ
Body
{
    "user_id": "feurhv",
    "book": {
        "id": "563428_fg6",
        "title": "Гарри Поттер и Тайная комната",
        "description": "Вторая книга серии о юном волшебнике",
        "image_url": "url", //опциональный
        "author": {
            "fist_name": "Джоан",
            "middle_name": "Кэтлин", //опциональный
            "last_name": "Роулинг",
            "short_description": "Английская писательница" //опциональный
        },
        "publisher_name": "Поттермо паблишинг",
        "publisher_year": "08.12.2015",
        "pages_count": 373,
        "language": "русский",
        "content_url": "url" // .epub, .pdf
  }
}
2. Загрузка книги по ссылке
Параметры
Название
Тип параметра
Обязательность
Описание
Authorization
HEADERS

AWS4-HMAC-SHA256


Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request, SignedHeaders=host;range;x-amz-date, Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024


Данные по авторизации FE получает от BE.

API издательства
1. Метод загрузки каталога книг

Запрос
Параметры
Название
Тип параметра
Обязательность
Описание
Authorization
HEADERS

Bearer <token>


token = "jhdtd_utdtrdgf5hgvjh_67543"

<version_api>
PATH

Текущее значение - v1

query
PATH
consumer_id
QUERY

Идентификатор потребителя API

Ответ
{
    "catalogue": [
     {
        "id": "563428_fg6",
        "title": "Гарри Поттер и Тайная комната",
        "description": "Вторая книга серии о юном волшебнике", //opt
        "image_url": "url", //opt
        "autorName": "Джоан_Кэтлин_Роулинг",
        "autorShort_description": "Английская писательница", //opt
        "publisher_name": "Поттермо паблишинг",
        "publisher_year": "08.12.2015",
        "pages_count": "373", //min
        "language": "русский"
    },
{
        "id": "767928_аg8",
        "title": "Гарри Поттер и Узник Азкабана",
        "description": "Третья книга серии о юном волшебнике", //opt
        "image_url": "url",
        "autorName": "Джоан_Кэтлин_Роулинг",
        "autorShort_description": "Английская писательница", //opt
        "publisher_name": "Поттермо паблишинг",
        "publisher_year": "08.12.2015",
        "pages_count": "475", //min
        "language": "русский"
    }
 ]
}

2. Метод загрузка контента: файлы книг //общий для текста и аудио

Запрос
Параметры
Название
Тип параметра
Обязательность
Описание
Authorization
HEADERS

Bearer <token>


token = "jhdtd_utdtrdgf5hgvjh_67543"

Ответ
["url", "url"] //тип файла определяем по расширению - text: .epub, .pdf; audio: .wav, .mp3
ADR MTS_Library.001
Автор
Цапкин Александр Валерьевич

Статус
draft

Содержание
ТЗ или описание

Контекст
Продукт МТС Библиотека активно развивается, добавляется новый функционал. В частности, ранее контент хранился на стороне партнера Литрес и соответственно скачивание контента нагружало инфраструктуру партнера. Сейчас идет процесс по переносу контента на сторону МТС.

Проблема
В текущей архитектуре планируется, что контент будет скачиваться к пользователю с использованием инфраструктуры проекта. Но с учетом резкого ожидаемого роста пользователей это может вызывать непредсказуемую загрузку текущего функционала (сетевые интерфейсы, API шлюз и прочее). Необходимо принять решение о том, как будет настроена инфраструктура проекта и какие микросервисы будут созданы (доработаны) для скачивания данных.

Рассмотренные варианты
В качестве вариантов реализации было рассмотрено 2 сценария.

Постоянные ссылки
Ссылки общие и прямые, отдаются всем, у кого есть подписки в приложении. Проверка ссылки происходит за счет проверки прав пользователя после нажатия на ссылку. TTL ссылки не ограничен.

Плюсы
  • Практически не требует доработки на существующем "монолите"
  • При отдаче контента нет необходимости каждый раз генерить новую ссылку

Минусы
  • Необходимость хранить дубль базы пользователей в микросервисе проверки ссылок

Разовые ссылки
Для каждой пары пользователь-контент создается разовая ссылка. После нажатия происходит проверка наличия ссылки в базе, ее принадлежности пользователю. TTL ссылки ограничен.

Плюсы
  • Нет необходимости хранить и поддерживать в актуальном состоянии дубль базы пользователей
  • Удобство хранения разовых ссылок в любых базах, включая NoSQL
  • Выставление TTL для ссылок

Минусы
  • Доработки "монолита"
  • Небольшие задержки при отдаче ссылки из-за необходимости сгенерить новую разовую ссылку

Решение
Выбрать вариант с разовыми ссылками. Он безопаснее, нет необходимости хранить дубль базы пользователей в сервисе проверки, ссылки создаются и хранятся в сервисе проверки ссылок.
Выделить под скачивание контента отдельную инфраструктуру. Сетевые интерфейсы, веб-сервера (Nginx), отдельный микросервис проверки пользователя CheckService (можно или нет ему скачивать контент), модули проксирования S3Service для трафика с S3 (MWS).

Шаблон ADR

_

_

Категория
Function
Границы
Product
Продукт
код продукта из PPInfo, если границы затрагивают только один продукт
Статус
Proposed
Дата создания
-
Дата последнего изменения
-
Владелец
укажите владельца, начав набирать с @
Участники решения
укажите участников, начав набирать с @
Ревью на уровне трайба
Используйте "@" для её связывания с пользователем и "//" для выбора её даты завершения.
Ревью на уровне кластера
Используйте "@" для её связывания с пользователем и "//" для выбора её даты завершения.
Ревью на уровне ЦК/ЦП
Используйте "@" для её связывания с пользователем и "//" для выбора её даты завершения.
Ссылка на родительский ADR
ссылка на родительский ADR, в рамках которого принимается данное решение
Ссылка на эпик из трэкера (Jira),
в рамках которого внедряется решение
ссылка на эпик из трэкера (Jira), в рамках которого внедряется решение
Ссылка на заменяемый ADR
ссылка на устаревший ADR, связанный с текущим ADR
Ссылка на архитектурное описание
ссылка на схему/диаграмму, которую объясняет текущий ADR
<!-- Категория ADR:  Function|Technology|Structure|Integration|Non-function|Data (см. https://confluence.mts.ru/pages/viewpage.action?pageId=375425483) -->

<!-- Границы ADR: Enterprise - если влияние на экосистему|Cluster - если влияние на Кластер|Tribe - если влияние на Трайб|Product - если влияет только на продукт -->
Контекст
<!-- Описание:
- причин, побудивших принять решение
- ограничений, действовавших на момент принятия решения
- проблемы, требующей решения -->
Варианты решения
<!-- Описание рассмотренных вариантов.
Обязательно перечислить критерии сравнения альтернатив.
Пример критериев - соответствие принятым в компании архитектурным принципам (указать конкретные релевантные принципы).
Должно быть понятно, как критерии сравнения связаны с бизнес-приоритетами и драйверами из контекста. -->
Решение
Описание решения
<!-- Описание выбранного решения.
Решение должно быть сформулировано чётко ("Мы используем...", "Мы не используем", а не "Желательно.." или "Предлагается...").
Должна быть понятна связь между решением и проблемой. -->
Последствия
<!-- Положительные и отрицательные последствия (trade-offs). Арх. решения, которые потребуется принять как следствие принятого решения. Если решение содержит риски, то описано, как с ними планируют поступить (за счет чего снижать, почему принять).
Арх. решения, которые потребуется принять как следствие принятого решения.
Если решение содержит риски, то описано, как с ними планируют поступить (за счет чего снижать, почему принять). -->
Ссылки
<!-- Здесь добавлены дополнительные ссылки (либо пусто)-->
Шаблон описания API
Основная информация
Общая информация

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

_

_

Автор
ФИО, кто пишет или правит документ
Задача
Ссылка на задачу (например, JIRA) или описание задачи
Бизнес постановка/User story
Описание какую пользу приносит эта задача пользователям
Связанные документы
Описание use case
Описание API

Раздел содержит таблицу с информацией об API и тестовый URI
Запрос
Параметр - название параметра
Тип параметра - указать тип данных параметра с ограничениями по длине если они есть
Тип данных - тип данных параметра (с ограничениями по длине если они есть)
Типы данных
Обязательность - да/нет
Описание - понятное описание для чего используется параметр
Пример запроса
curl --location --request POST 'https://..../&parameter_5=primer_parameter_5' \
--header 'parameter_1: ....' \
--header 'parameter_2: ....' \
--data-raw '{"parameter_3": "Пример для Параметра 3",
             "parameter_4": {
                "parameter_4.1": "Пример для Параметра 4.1",
                "parameter_4.2": 1,}
            }'
Проверки
Раздел содержит таблицу:

Параметр - название параметра
Проверка - условие и результат проверки

_

_

Параметр

Условие
name

Пример: Максимальная длина 100 символов.

Если количество символов >100, то сервис возвращает ответ с кодом 400 и описанием "Максимальная длина name 100 символов"

Ответ
Положительный ответ

Параметр - название параметра
Тип параметра - указать тип данных параметра с ограничениями по длине если они есть
Тип данных - тип данных параметра (с ограничениями по длине если они есть)

Типы данных
Обязательность - да/нет
Правила заполнения - описание как получить значение параметра
Описание - понятное описание для чего используется параметр
Пример ответа
{
    "parameter_1": "Пример для Параметра 1",
    "parameter_2": {
        "parameter_2.1": "Пример для Параметра 2.1",
        "parameter_2.2": 1,
    }
}
Ответ с ошибками

Код - код ошибки
Описание - описание ошибки

_

_

Код

Описание
400
Максимальная длина 100 символов
405
Неправильный ввод
Описание интеграции
Диаграмма последовательности

Схема последовательности работы метода
Алгоритм
Подробный алгоритм работы метода. Точное и недвусмысленное описание
Понравился спринт?