Интеграция и внешние идентификаторы

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

Интеграция и внешние идентификаторы

Сначала сформулирую капитанские тезисы, а потом перейду к истории из реальной практики.

  • Контролируйте характер и размерность импортируемых данных.
  • Храните внешние идентификаторы с использованием универсальных типов данных.

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

В публичном API тип данных PersonID определён как long — 64-разрядное целое число. Выбранной размерности более чем достаточно, поскольку предполагается хранение данных не более чем для 100 миллионов человек. Всё работает прекрасно уже 15 лет, однако на этапе импортозамещения БД документов вскрылся один критический недостаток.

Во-первых, было обнаружено, что есть документы, у которых значение PersonID значительно превышает заявленные 100 миллионов. Например, максимальное значение на сегодняшний день составляет 9999998756120159. Во-вторых, данные свидетельствуют о значительных пропусках в диапазонах PersonID, хотя представители внешней системы заверяли, что у них обычный Sequence в PostgreSQL. Наконец, в ходе дальнейшего разговора выяснилось, что во внешней БД PersonID представлен типом данных NUMERIC(20) — целым числом размерностью до 20 десятичных разрядов. Это была вишенка на торте, т.к. в публичном API сейчас используется long, который позволяет работать с числами до 18 (с "хвостиком") десятичных разрядов. Что это значит для нас? Если такие скачки в генерации продолжатся, значения PersonID очень скоро выйдут за пределы размерности long и наш сервис не сможет сохранять новые документы. Последнее означает полную остановку процессов на неопределённый срок, что совершенно недопустимо.

Выхода из этой ситуации два:

  • В своей системе использовать тип данных, который один-в-один соответствует типу данных во внешней системе.
  • В своей системе использовать универсальный тип данных, а преобразование типов делать только на уровне сетевого взаимодействия.

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

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

P.s. Посмею напомнить, что у меня есть Telegram-канал "Архитектоника в ИТ", где я публикую материал на похожие темы примерно раз в неделю. Подписчики меня мотивируют, но ещё больше мотивируют живые дискуссии, ведь именно в них рождается истина. Поэтому подписывайтесь на канал или на мой блог здесь. Будем обмениваться опытом и мнениями. ;-)

Начать дискуссию