Блог СУБД SoQoL

Первая интеграция SoQoL

Когда у тебя рядом команда разрабатывает новую СУБД SoQoL с очень заманчивыми возможностями, очень хочется попробовать ее на проекте, более-менее приближенном к реальности. Благо у нас есть такие не слишком большие проекты, позволяющие испробовать новые технологии.

Свой первый эксперимент с SoQoL мы провели на системе автоматизации учета инфраструктуры с кодовым названием AIM, которая выросла из учебного проекта. Что из этого получилось? Вы узнаете, прочитав нашу небольшую заметку.

Что такое AIM?
AIM — наш внутренний сервис по автоматизации учета использования инфраструктуры компании между проектами и отделами. Он позволяет:
  • Организовать учет всей инфраструктуры компании (физические сервера, виртуальная инфраструктура, VPN, конфигурация CI, пространство для контейнеров, лицензии и др.) в разрезе проектов и отделов
  • Видеть все выделенные ресурсы и их статус на уровне проектов, отделов и компании в целом

Работа с AIM организована в виде формирования электронных заявок на выделение инфраструктурных объектов и их обработки.

Какие технологии
Backend сервиса разработан на Java с использованием Spring + Hibernate.
Для хранения данных используется PostgreSQL, система миграций Liquibase.
Фронт сервиса разработан на JavaScript, TypeScript + фреймворк ReactJS.

Задача
Летом 2022 года мы решили попробовать перевести AIM с PostgreSQL на нашу новую СУБД SoQoL. Альфа-версия уже поддерживала ряд функций, которые обеспечивали работу приложения, поэтому процесс перехода не требовал глобальных изменений и свёлся к следующим действиям:
  • Изменение скриптов создания БД
  • Правка кода приложения
  • Интеграция системы миграции с SoQoL

Первый этап содержал действия, направленные на изменение исходных структур таблиц:
  1. Провели сверку типов столбцов таблиц. Каждому типу PostgreSQL был поставлен в соответствие тип SoQoL: BYTEA – BLOB, TEXT – CLOB, REAL – NUMBER. Также увеличили значение, ограничивающее максимальный объем информации для полей типа VARCHAR. В SoQoL данное ограничение влияет не на длину строки, а на количество байтов, хранящих строку.
  2. Удалили неподдерживаемые (пока) альфой структуры: внешние ключи (FOREIGN KEY), ограничения (CONSTRAINT) и триггеры (TRIGGER). На первом этапе, до появления этих возможностей в SoQoL, посчитали это временным и приемлемым шагом.
  3. Если в таблице использовался первичный ключ с автоувеличением (SERIAL), выполняли его замену на последовательности (SEQUENCE).
  4. Также необходимо было учесть, что NULL-значение является уникальным в рамках использования модификатора UNIQUE. И в случаях, где разрешались множества записей без значений, необходимо было удалить модификатор или прибегнуть к иной логике решения задачи.

Следующий этап был связан с правками кода бэкенда: использование генерации первичных ключей через последовательности, а также модификация SQL и HQL (Hibernate Query Language) запросов.
Первые запуски бэкенда выявили необходимость правок диалекта: Java-типы не сопоставлялись с типами столбцов БД, а также требовалась реализация различных методов, использованных в запросах на HQL.

В БД PostgreSQL также использовалось хранение данных в столбце типа JSONB. Аналогичные результаты были достигнуты в SoQoL посредством хранения в БД текстового поля и создания конвертера, преобразующего поле в Java-тип, описывающий JSON структуру.

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

База данных, в рамках которой производилась работа, содержит порядка 70-ти таблиц и ручная работа по их созданию и модификации могла привести к ненужным ошибкам, и эта работа была переложена в систему Liquibase. Коротко о плане работ: необходимо было изменить процесс генерации таблиц, в которых хранится информация о миграциях, а также реализовать сервером БД требуемые библиотекой функции.

Для решения первой задачи можно было внести правки в исходный код библиотеки, но это означало бы привязку к конкретной версии и связанные с ней дальнейшие работы по актуализации состояния. Liquibase же позволил создать универсальное решение, которое переопределяет поведение нужных методов и добавляет их в контекст исполнения. То есть все изменения относительно SoQoL находятся в отдельном проекте, который служит надстройкой к исходной библиотеке. О второй задаче позаботились разработчики сервера.

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

Тестирование функциональности AIM
Для тестирования системы были привлечены пользователи приложения AIM. Проверка включала в себя всю функциональность приложения, а именно:
  • Создание и редактирование персональных и проектных заявок;
  • Работа с пулами и типами ресурсов;
  • Системные настройки приложения;
  • Мониторинг активных ресурсов.

Углубленное тестирование сценариев использования выявило отклонения в диалекте и сервере БД. Одна из ошибок возникла при трансляции HQL-запроса на основе диалекта. В теле запроса использовался оператор IN, в который время от времени передавалось пустое множество, и ожидалось, что результирующая выборка будет пуста. Доработка диалекта решило эту задачу.

Выводы
Миграция AIM на SoQoL помогла нам найти и исправить ошибки в СУБД, выявить недостающую функциональность и внести ее будущий план работ. Был доработан диалект Hibernate для SoQoL. Взаимодействие же приложения AIM стало более обобщенным по отношению к различным СУБД.

Работы по миграции AIM на SoQoL ожидаемо растянулись во времени, т.к. приходилось ждать новых сборок СУБД от серверной команды, но в целом заняли не более 160 часов одного специалиста, который их проводил.