Всем привет! На связи Владимир Колеснев и Владимир Беневоленский из ИТ-команды подразделения ДОМ.РФ Земли. Здесь мы уже рассказывали о том, чем мы занимаемся, но напомним: в ДОМ.РФ мы создаём систему автоматизации вовлечения в оборот неиспользуемого федерального имущества. Другими словами, мы разрабатываем продукт на Б24, в котором земельные участки (ЗУ) проходят долгий путь от появления в системе до реализации на торгах. 

Сокращённо мы СУЗФ – система управления земельным фондом. Почему наша система работает на Битрикс24? Да бог его знает, так было задумано свыше. Но, как говорится, от своей судьбы не уйдешь. Проблема, с которой мы столкнулись, случилась бы в любом случае, независимо от того, использовали бы мы Б24 или нет.

СУЗФ – огромная система с кучей сущностей и процессов, в которой, естественно, всё работает как швейцарские часики (спасибо нашему тимлиду). Мы оперируем 25-30 сущностями и ~900 свойствами, но основные сущности – это лоты, земельные участки, торги, документы (кстати, документов у нас около трёхсот тысяч). Каждая сущность имеет свою логику создания и изменения. Это могут быть различные источники модификаций. Например, земельный участок может создаваться/модифицироваться внутри системы логикой трансформации (межевания) участков / обновляя какие-либо данные через выписку ЕГРН (единый государственный реестр) или обновляя гео-данные через интеграцию с сервисами наподобие DaData и пр. Причем нужно заметить, что обновления  так же могут происходить по событию (EventHandler) и по интервалу времени (Cron).

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

Проблема 

И жили бы мы так долго и счастливо, но «бизнес» интересовался природой случайной модификации элемента. С ростом системы генерировать отделом разработки ответы с причинами изменений стало уже невозможно. Проблема возникла, когда мы конкретно перестали понимать, почему какой-либо элемент сущности создался или изменил свои параметры.

Идея

Возник вопрос: как бы нам красиво снять с себя ответственность за модификации элементов? Нам был нужен механизм: единая точка входа для создания/изменения элемента и разные данные в зависимости от источника.

Реализация

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

Как это работает? Каждый раз, когда происходит создание/обновление элемента, эта система логирует источник и список измененных полей. Например, если земельный участок был изменен через выписку ЕГРН, система сохранит эту информацию и привяжет ее к элементу участка. Таким образом, у нас всегда будет доступ к полной истории изменений элемента и понимание, почему он был создан или изменен, когда и кем.

 У нас есть базовый абстрактный класс для добавления и изменения элемента (рис.1):

 

Рис.1. Базовый класс
Рис.1. Базовый класс

 Внутри этого класса есть:

  • Метод getDescription(), который возвращает описание логики модификации/создания элемента

  • Метод getFields(), в котором подготавливаем поля для элемента, данные из этого метода будем получать в методе сохранения save() в базовом классе

  • Метод onBefore(), в котором мы можем валидировать переданные данные перед сохранением либо выполнять какую-то дополнительную логику, необходимую до сохранения

  • Метод onAfter() для дополнительной логики после сохранения элемента

  • Метод createOrUpdate(), который изменяет/создает элемент. В него мы можем передать ID элемента, если элемент нужно модифицировать.

Рис.2. Метод createOrUpdate()
Рис.2. Метод createOrUpdate()

Внутри метода createOrUpdate() мы сохраняем элемент через метод save() и сохраняем в логи результат сохранения элемента (рис.3). Внутри метода save() мы только вызываем метод createOrUpdate(), но уже из класса для работы с элементами инфоблоков (инфоблок – одна из сущностей БД Б24).

Рис.3. Обновление/создание элемента (метод из класса для работы с элементами инфоблоков)
Рис.3. Обновление/создание элемента (метод из класса для работы с элементами инфоблоков)

 Таким образом выглядит структура источников для элементов (рис.5):

Рис.4 Структура источников элементов
Рис.4 Структура источников элементов

Классы источников мы наследуем от базового класса (рис.5):

Рис.5 Класс источника
Рис.5 Класс источника

Если в функцию createOrUpdate() мы передаём ID элемента, элемент обновляется, если не передаём – элемент создаётся.

Сохранение элемента происходит таким образом (рис.6):

Рис.6 Сохранение элемента
Рис.6 Сохранение элемента

Данные, которые мы передаем в конструктор должны содержать в себе максимальный набор «сырых» данных, а различная логика и преобразования должны содержаться уже внутри сорса. Таким образом вся логика изменения элемента для данного сорса содержится в одном едином классе.

Сохранение элемента может быть вызвано каким-либо событием (EventHanlder) либо запущено по истечении интервала времени.

Для таких случаев у нас есть два интерфейса для класса источника: Eventable и Periodic. От Periodic добавляется метод, в котором определяется, пора ли нам запустить сохранение элемента. От Eventable – метод, в котором в класс-регистратор обработчиков событий мы возвращаем событие сразу с его обработчиком.  

Интерфейс Eventable на рис.6. и Periodic на рис.7. 

Рис.7 Интерфейс Eventable
Рис.7 Интерфейс Eventable
Рис.8 Интерфейс Periodic
Рис.8 Интерфейс Periodic

На рис.8 мы регистрируем обработчики событий.

Рис.9 Регистрация обработчиков событий
Рис.9 Регистрация обработчиков событий

Итоги

 Этот механизм позволяет нам решить несколько проблем.

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

Кроме того, это позволяет анализировать данные и выявлять тенденции и паттерны в модификации элементов. Мы можем использовать эти данные для оптимизации процессов и повышения эффективности работы системы.

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

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

Комментарии (1)


  1. Johan_Palych
    20.11.2023 16:43

    Каким боком ДОМ.РФ к Donald Trump 2024 presidential campaign?