Подход к пагинации записей из разных источников

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.
Изображение от Freepik
Изображение от Freepik

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

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

API получения списка объектов
API получения списка объектов

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

Запрос всех данных из двух источников с последующей агрегацией и фильтрацией силами рассматриваемого сервиса можно отбросить сразу, в силу неэффективности. Предлагаю рассмотреть подход, разделяющий все страницы объектов на две группы по признаку их источника. При этом все объекты из нового источника данных будут расположены в первых i страницах выдачи. Все объекты из старого источника данных будут расположены на страницах, начиная с i+1. Такое разделение на две группы происходит с учётом указанных в запросе фильтров.

Совместная пагинация старых и новых объектов
Совместная пагинация старых и новых объектов

Алгоритм состоит из следующих шагов:

  1. В исходном запросе присутствуют: запрашиваемая страница requested_page, желаемый размер страницы page_size и опциональные параметры фильтрации.

  2. Получение общего количества старых объектов total_items_old, попадающих в выборку.

  3. Вычисление количества страниц старых объектов
    total_pages_old = ceil(total_items_old/page_size).

  4. Получение общего количества новых объектов total_items_new, попадающих в выборку.

  5. Вычисление количества страниц новых объектов
    total_pages_new = ceil(total_items_new/page_size).

  6. Если запрашиваемая страница requested_page попадает в диапазон
    [1, total_pages_new], то делаем запрос данных из нового места хранения объектов.

  7. Иначе, делаем запрос в старое место хранения, не забыв преобразовать номер нужной страницы actual_page = requested_page - total_pages_new.

  8. В ответе в качестве общего количества страниц и объектов следует отдать (total_pages_old + total_pages_new) и (total_items_old + total_items_new) соответственно.

  9. В результате запроса нужно отдать список объектов, полученный в п.6 или п.7.

Схема алгоритма
Схема алгоритма

Описанный подход содержит несколько компромиссов. Серьёзный минус - это невозможность использовать сортировку агрегированного списка объектов. Менее значительный - наличие страницы с номером total_pages_new, которая в большинстве случаев будет содержать меньше записей, чем запрошено. Если такое поведение неприемлемо, то можно усложнить расчёт отступов, чтобы заполнить эту страницу объектами из старого источника данных.

Спасибо за внимание, пусть ваши временные решения не становятся постоянными.

Источник: https://habr.com/ru/articles/736390/


Интересные статьи

Интересные статьи

С первого релиза Brave ведёт наиболее агрессивную из всех браузеров политику в отношении сторонних кук и других данных — мы по умолчанию делаем недоступными сторонние хра...
Мы делаем все, чтобы платформа Android была безопасной для всех пользователей на всех устройствах. Каждый месяц выходят обновления системы безопасности с исправлениями уязви...
В процессе прохождения игр пользователи стремятся к победе посредством достижения целей и задач, определяемых многими факторами. Навыки, мотивация, ресурсы и мощность ава...
Я пишу на питоне лет пять, из них последние три года — развиваю собственный проект. Большую часть этого пути мне помогает в этом моя команда. И с каждым релизом, с каждой новой фичей у нас вс...
Академическое знание давно уже обитает в интернете, и как и любая информация, индексируется поисковыми машинами и базами данных. Я говорю о более широкой категории знаний, чем STEM (Science Techn...