Диалог плюс норильск

В чем заключается подводный камень?

id (integer) — идентификатор записи в БД;
managerId (integer) — идентификатор сотрудника;
clientPhoneNumber (string) — номер телефона клиента;
dialog (string) — запись диалога в текстовом виде;
date (string) — дата диалога.

Важно: пагинация относится к одной из best practiсes проектирования API и используется не только при взаимодействии «фронтенд-бэкенд», но и при взаимодействии «бэкенд-бэкенд».

При получении запроса на эндпоинт необходимо осуществить валидацию его параметров.
Если валидация успешна, необходимо выполнить запрос на получение X записей из БД, пропустив предыдущие Y записей.

В этом случае, в описании метода выше изменятся только следующие строки:

page (integer) — номер страницы. Параметр обязательный, передается в query.
recordsPerPage (integer) — количество записей на странице. Параметр обязательный, передается в query.
(Например: GET api/v1/dialogs?page=3&recordsPerPage=5)

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

Описание метода

Теперь нам необходимо определить формат ответа, формат запроса, HTTP-метод и URL, на который мы будем отправлять запрос.
Особой разницы с чего начинать проектирование нет, я обычно начинаю с метода.

В этом случае на помощь приходит простой подход — пагинация. Это значит следующее:

Спецификация (формат данных)

Метод спроектировали, переходим к форматам данных.

1. В случае внутренней ошибки возвращать ответ 500 Internal Server Error.
2. В случае ошибки валидации параметров запроса возвращать ответ 400 Bad Request.

Рассмотренный выше способ пагинации называется offset-based pagination. Он прост в реализации и эффективен, для небольших объемов запрашиваемой из БД информации, так как с увеличением номера страницы возрастает время запроса данных в БД, а также возникает проблема с консистентностью данных в ответе, в случае с часто обновляемыми данными.

OpenAPI

Вспомним, что у нас в БД уже лежит диалог клиента с менеджером. Идем смотреть какие же там поля. Допустим, их там всего пять:

В этом случае, при попытке сделать запрос в БД и извлечь все записи хотя бы за один день (а их, напомню на 30 Мб объема), мы получим, как минимум, длительное время отклика (технические нюансы про блокировки в БД, опять же, опустим), которое точно не будет радовать наших пользователей, когда они каждый раз будут обновлять или заходить на страницу, и никак не ускорит процесс их работы.

Ниже приведена иллюстрация взаимодействия для привлечения внимания 🙂

JSON-схема для описания формата данных запроса (нужна только для метода POST) будет выглядеть следующим образом:

P.S. X=recordsPerPage; Y=X*(page-1).
P.P.S. Тут вообще можно написать SQL-запрос типа SELECT * FROM dialogs OFFSET Y LIMIT X, чтобы разработчики крепче вас любили 🙂

Еще один из методов называется keyset pagination (seek method). Основная его идея — использовать комбинацию ключей для итерационного поиска следующих записей в отсортированном массиве.

Какие еще бывают реализации пагинации

Существует несколько best practices проектирования REST API. Список не исчерпывающий, а построенный на основе моего личного опыта.

Допустим, что наша компания средней руки и у нас целых 100 менеджеров. Каждый из них совершает за день в среднем 30 звонков по 10 минут. Итого получаем 3000 диалогов в день. Каждый 10-ти минутный диалог в текстовом виде будет «весить» в среднем 10 Кб, и за день таких диалогов наберется на 30 Мб.

Обычно такой подход используется, если запрос имеет большое количество параметров, так как при использовании метода GET можно столкнуться с ограничением длины URL-строки в 2048 символов, и параметры будут потеряны при передаче на сервер. Плюс к этому, если передаваемые данные чувствительны, то безопаснее будет передавать их в теле (requestBody) POST-запроса.

OpenAPI спецификация для метода GET

Если пользуемся OpenAPI — указываем ссылку на спецификацию в swagger (или другом аналогичном инструменте).
Если пользуемся JSON-схемой, прикладываем файл со схемой запроса и ответа.

Рекомендую ознакомиться с замечательной статьей со сравнением offset pagination и keyset pagination.

Ниже приведен шаблон описания REST API-метода. Будем использовать GET метод для запроса данных.

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

JSON-схема для описания формата данных в ответе будет выглядеть следующим образом:

Представление метода GET в Swagger

Можно отправить тот же самый запрос и методом POST (для наглядности вместе с еще одним атрибутом — пусть им будет date ).

В этой статье я постарался максимально емко изложить принцип проектирования метода REST API с пагинацией, предназначенного для запроса данных из БД на примере JSON-схемы и спецификации OpenAPI.

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

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

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

Более производительный и устраняющий проблемы с консистентностью данных метод называется cursor-based pagination, когда вместо offset используется cursor — указатель на место в памяти, содержащее результаты select запроса к БД. Поэтому курсор вернёт только те данные, которые существовали на момент начала транзакции в базе.

Давайте посмотрим, как это будет выглядеть в формате спецификации OpenAPI на языке YAML.

Зарегистрировано Федеральной службой по надзору в сфере связи, информационных технологий и массовых коммуникаций (Роскомнадзор). Свидетельство Эл № ФС77-54527 от 21.06.2013 г.

Как реализовать это в коде мы оставим на откуп нашим доблестным разработчикам, а так как у нас в команде принят API-first подход, то сначала нам придется спроектировать для этого метод REST API. Проектировать будем на примере JSON-схемы и OpenAPI.

Мы — в роли обычного системного аналитика, работающего в этой компании над бэкендом систем, отвечающих за продажи. И вот к нам приходит наш владелец продукта (PO) и просит сделать так, чтобы сотрудники аналитического отдела могли видеть у себя в интерфейсе CRM-системы запись о каждом обращении потенциального клиента и содержание его диалога с менеджером по продажам в текстовом виде.

Подробнее ознакомиться с проектированием REST API, форматами OpenAPI и JSON-Schema вы можете в моей статье на Хабре.

А также с этой статьей о способах реализации пагинации в PostgreSQL.

Можете скопировать эти YAML сюда, чтобы самостоятельно поизучать и посмотреть реализацию в Swagger. Или увидеть представление спроектированных методов в интерфейсе Swagger на изображениях ниже .

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

page (integer) — номер страницы. Параметр обязательный, передается в requestBody.
recordsPerPage (integer) — количество записей на странице. Параметр обязательный, передается в requestBody.
date (string) — дата диалога. Параметр необязательный, передается в requestBody.

Представим, что есть компания, продающая домашних питомцев. И вот ее менеджеры обзванивают потенциальных клиентов и по 10-15 минут уговаривают их купить пушистиков, рассказывая о том, какие они милые, добрые и умные.

Эту и другие статьи по системному анализу и IT‑архитектуре, вы сможете найти в моем небольшом уютном Telegram‑канале: Записки системного аналитика

Учредитель — ООО «МедРейтинг». Адрес редакции: 350015, Краснодарский край, г. Краснодар, ул. Буденного, д. 182, офис 87.

Единственный недостаток этих методов — нельзя перейти на определенную страницу.

Зарегистрировано Федеральной службой по надзору в сфере связи, информационных технологий и массовых коммуникаций (Роскомнадзор). Свидетельство Эл № ФС77-54527 от 21.06.2013 г.

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

Источники:

https://habr.com/ru/articles/846130/&rut=a0131f45ea3a067ac567b51b501560774da5309d6228b021da74f62e9cc30395
https://2gis.ru/norilsk/firm/70000001025748369&rut=9333f68f8a892849affdb16243fe3eabbad42eb35b63b6994d9973bde7623bee
https://doctu.ru/norilsk/clinic/medicinskijj-centr-dialog-pljus/doctors&rut=71d85546fd156f29c5f1b6b68f168a9096de24c0e4e1701614c40abcc3dd9b48
https://prodoctorov.ru/norilsk/lpu/71596-dialog-plyus/otzivi/&rut=02a05f875512a196244b2d4f612ba3ce0b40c7766f2cc7103abb06f1e94234d8
https://doctu.ru/norilsk/clinic/medicinskijj-centr-dialog-pljus/reviews&rut=a726fd603dc1fd0321070699c6a1f7270e054341d7a85a61aa0969a4803b47a9
https://2gis.ru/norilsk/firm/70000001025748369/tab/prices&rut=b4bf52bd945f56ffc134a27b003be043b3467f86839f5da5b6e0fe93b4f6b72e
https://2gis.ru/norilsk/branches/70000001025748368/filters/district_id%3D10696659000360964&rut=7a2f436d821aa7a388beae047257bb44ac82217489aaf454ce497c16bca10781
https://prodoctorov.ru/norilsk/lpu/71596-dialog-plyus/price/&rut=d2ebcae14541ff156da3885871dc3409167c034b92bf50e4f97fdf620bd5d2ad
https://spravkainform.ru/russia/norilsk/vrachebnye-medicinskie-komissii/dialog-plyus&rut=3b5693f9eaedd0fc4f9e883ee58179bed58416ec405cf7d570e5410b85f33bae