Требования к модели данных#

В модели данных необходимо описать события (event), которые будут обрабатываться при работе сервиса DataSpace Subscription.

Явные события в модели данных#

Явное событие может выступать как в роли самостоятельного агрегата, так и являться дочерним объектом одного из существующих агрегатов в модели — для этого у события должна быть объявлена ссылка на родительский класс (размеченная атрибутом parent=»true»). Событие, у которого отсутствует родительская ссылка, является самостоятельным агрегатом.

Данный вид событий необходимо явно создавать в составе пакета команд.

Отличия явного еvent от класса:

  • для него определены только операции создания и поиска;

  • служит только для подписки на него;

  • не наследуется;

  • имеет плоскую структуру;

  • допустима ссылка на родительский класс для формирования агрегатной связи; event, у которого отсутствует родительская ссылка, является самостоятельным агрегатом;

  • обработанный всеми подписками event автоматически удаляется по истечении времени;

  • не реплицируется в хранилище данных и не отражается в логической модели для хранилища данных.

Пример описания события, являющегося самостоятельным агрегатом:

<model model-name="MyEventDemo" version="DEV-SNAPSHOT">
    <event name="MyEvent">
        <property name="message" type="String"/>
    </event>
</model>

Пример события, которое входит в агрегат Product:

<model model-name="ProductEventDemo" version="DEV-SNAPSHOT">

  <class name="Product" label="Продукт" lockable="true">
    <property name="name" type="String" label="Наименование"/>
  </class>

  <event name="ProductEvent">
    <property name="message" type="String"/>
    <property name="product" type="Product" parent="true"/>
  </event>

</model>

Для свойств событий допустимыми атрибутами являются: name, type, parent, label, length, scale, mandatory, default-value.

Внимание!

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

BaseEvent#

Любое событие наследует от абстрактного класса BaseEvent, имеющего следующие свойства:

Свойства BaseEvent:

Свойство

Тип

Описание

objectId

String (254)

ID события

creationTimestamp

OffsetDateTime

Метка времени создания события

type

String (254)

Тип события (имя класса события).
Не отображается в данных события при публикации

status

enum

Статус обработки события:
new — создан,
processed — обработан перекладчиком (конечный статус).
Не отображается в данных события при публикации

lastChangeDate

Date

Время последнего изменения записи

aggregateRootId

String (254)

ID корня агрегата
*Если событие является корнем агрегата — поле aggregateRootId отсутствует, аналогично обычным классам.
Не отображается в данных события при публикации

ownerId

String (254)

ID тенанта

partitionHash

Long

Предрассчитанный хеш для деления по партициям.
Не отображается в данных события при публикации

Автоматические события в модели данных#

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

Отличия автоматического еvent от класса:

  • для него определена только операции поиска;

  • служит только для подписки на него;

  • не может иметь вручную объявленные свойства;

  • обязательна ссылка на родительский класс для формирования агрегатной связи;

  • обработанный всеми подписками event автоматически удаляется по истечении времени;

  • должно наследоваться от предопределенных базовых типов автоматических событий (подробно будут рассмотрены далее):

    • BaseChangeEvent,

    • BaseObjectEvent,

    • BaseTrackingEvent,

    • BaseSnapshotEvent,

    • BaseMergeEvent,

    • BaseHistoryEvent;

  • не реплицируется в хранилище данных и не отражается в логической модели для хранилища данных.

События слияния/разъединения (BaseMergeEvent)#

Отдельным видом событий изменения являются события слияния/разъединения.

Если сконфигурировать подписку на события слияния/разъединения, то при выполнении операции слияния/разъединения сформируется событие слияния/разъединения, которое будет опубликовано в соответствии с подпиской.

Для этого в модели предметной области необходимо объявить event, унаследованный от BaseMergeEvent при помощи атрибут extends со значением BaseMergeEvent. Этот event необходимо связать с классом, содержащим референс, обрабатываемый при слиянии/разъединении.

Внимание!

Способ объявления при помощи признака merge-event="true" является устаревшим, пользоваться им не следует.

Такие event не доступны для создания через пакет команд или mutation GraphQL. В качестве значения тенанта (атрибут ownerId) для таких событий устанавливается значение, равное значению тенанта того агрегата, в рамках которого произошли изменения.

Для событий слияния/разъединения обязательно наличие ссылки на родительский класс, но других собственных свойств для них задать нельзя.

Пример объявления:

<model model-name="MergeEventDemo" version="DEV-SNAPSHOT">

    <external-types>
        <external-type type="Client" merge-kind="Organization"/>
    </external-types>

    <class name="Product" label="Продукт" lockable="true">
        <property name="name" type="String" label="Наименование"/>
        <property name="code" type="String" label="Код"/>
        <reference name="client" type="Client" label="Идентификатор клиента"/>
    </class>

    <event name="ProductClientMergeEvent" extends="BaseMergeEvent">
        <property name="product" type="Product" parent="true"/>
    </event>

</model>

Собственные свойства BaseMergeEvent:

Свойство

Тип

Описание

mergeKind

String (254)

Вид слияния — параметр процесса слияния/разъединения

referenceName

String (254)

Имя обрабатываемой при слиянии ссылки

fromReference

String (254)

Предыдущее значение ссылки

toReference

String (254)

Новое значение ссылки

mergeFailed

Boolean

Признак успешного завершения процесса слияния/разъединения («true» — если процесс завершился неудачей, «false» или «null» — если успешно)

errorCode

String (5)

Код ошибки

errorMessage

String (254)

Сообщение об ошибке

События слияния/разъединения создаются автоматически сервисом DataSpace ReferenceUpdater.

Если процесс слияния/разъединения завершился успешно, то формируется event со значением поля mergeFailed = false.

Предусмотрена возможность создания события в том случае, если процесс слияния/разъединения завершился с ошибкой, требующей постороннего вмешательства. За это отвечает настройка сервиса дедубликации duplication.service.enable-failed-merge-events. По умолчанию формирование таких событий выключено: duplication.service.enable-failed-merge-events=false.

Если перевести настройку duplication.service.enable-failed-merge-events сервиса дедубликации в значение true, то при возникновении ошибки процесса слияния/разъединения будут создаваться события со значением поля mergeFailed = true. При этом также заполняются поля errorCode — код ошибки и errorMessage — сообщение об ошибке.

Виды ошибок, при которых формируется event со значением поля mergeFailed = true, предопределены.

Доступен вид ошибок UNIQ — ошибка нарушения уникальности.

Для подписки на неуспешные события слияния/разъединения необходимо использовать фильтр root.mergeFailed == true в поле criteria для подписки.

Примечание

Если функциональность обработки событий слияния/разъединения клиентов первый раз используется потребителем, начиная с версии компонентов DataSpace 1.11.0 и выше, и если настройка сервиса дедубликации duplication.service.enable-failed-merge-events установлена в значение true, то для подписки на успешные события слияния/разъединения достаточно использовать фильтр root.mergeFailed == false в поле criteria для подписки.

Если данная функциональность использовалась до версии 1.11.0, а также если настройка сервиса дедубликации duplication.service.enable-failed-merge-events установлена в значение true, то следует использовать фильтр coalesce(root.mergeFailed, false) != true в поле criteria для подписки.

Примечание

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

Диаграмма событийного обмена при слиянии/разъединении#

@startuml
title Публикация событий при слиянии/разъединении
participant "Master Data Management" as app
participant "DataSpace-StateMachine" as stm
participant "DataSpace-ReferenceUpdater" as reup
database "DataSpace DB" as db
participant "DataSpace-Subscription" as subs
queue "topic Kafka" as topic
participant "Подписчик" as subscriber1
app -> stm : событие\nо слиянии клиентов
stm -> db : создать задачу\nна слияние
db -> reup : получить и выполнить\nзадачу на слияние
reup -> db : найти все\nобъекты для слияния
reup -> db : для каждого объекта\n — заменить значение\nссылки на новое,\nсформировать событие слияния
db -> subs : прочитать\nновые события
subs -> db : выполнить запрос\nзаданный в подписке
subs -> topic : опубликовать\nсобытие через\ntopic Kafka
topic -> subscriber1 : прочитать\nсобытие
subs -> db : по прошествии\nзаданного периода\nудалить все данные\nсобытия и публикации
@enduml

События создания записи историцирования (BaseHistoryEvent)#

Данный тип событий применим только к историцируемым сущностям (см. Историцирование). Для них обязательно наличие ссылки на родительский класс, но других собственных свойств для них задать нельзя. Событие формируется при создании записи в истории родительской сущности. Для родительского типа можно объявить только один event, унаследованный от BaseHistoryEvent. Пример объявления:

<model model-name="HistoryEventDemo" version="DEV-SNAPSHOT">

    <class name="Account">
        <property name="number" type="String" length="32" unique="true"/>
        <property name="accountType" type="String" length="4" />
        <property name="currency" type="String" length="3" historical="true" />
        <property name="amount" type="Decimal" length="20" scale="2" historical="true"/>
    </class>
    <!-- создаем дочерний AccountHistoryEvent -->
    <event name="AccountHistoryEvent" extends="BaseHistoryEvent">
        <property name="account" type="Account" parent="true"/> <!-- Примечание: Тип `Account` историцируемый, т.к. есть историцируемые поля -->
    </event>

</model>

События отслеживания изменений (BaseChangeEvent, BaseObjectEvent, BaseTrackingEvent, BaseSnapshotEvent)#

События отслеживания изменений формируются в ответ на изменения отслеживаемых классов.

Таким образом дается возможность подписаться на изменение сущностей.

Для этого в модели предметной области необходимо объявить event, указав в качестве типа parent свойства тот класс, изменения которого необходимо отслеживать и формировать события. А также необходимо указать в атрибуте extends один из базовых, предопределенных классов событий изменения сущностей:

  • BaseChangeEvent;

  • BaseObjectEvent;

  • BaseTrackingEvent;

  • BaseSnapshotEvent.

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

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

В BaseChangeEvent и BaseTrackingEvent имеется возможность указать, изменения каких именно свойств необходимо отслеживать, при этом событие формируется при изменении любого из отслеживаемых свойств. Для этого в спецификации события event используется специальный элемент parents-property. BaseObjectEvent, BaseTrackingEvent и BaseSnapshotEvent отслеживают не только изменения, но и создание и удаление сущности.

Могут отслеживаться свойства следующих типов:

  • примитивные типы;

  • перечисления;

  • ссылки на другой класс (отслеживается изменение самой ссылки, а не сущности по ссылке);

  • reference;

  • свойства статусной модели (сгенерированные statusFor<наблюдатель>);

  • ссылки на справочники;

  • embeddable типы.

Свойства-коллекции указывать в качестве отслеживаемых нельзя.

Особенности обработки транзакции с созданием событий отслеживания изменений#

Для того чтобы формируемые события с сохранением состояния содержали актуальное значение всех сохраняемых свойств все отслеживаемые сущности блокируются при выполнении пакета (кроме операций создания, т.к. это не имеет смысла). В качестве альтернативы предусмотрена опция, позволяющая вместо блокировки выполнять повторное чтение обновленных сущностей непосредственно перед формированием события. Данную опцию можно включить настройкой dataspace-core.events.lock-updated-entity-for-change-event — значение по умолчанию false, т.е. обновленные сущности считываются повторно. К операциям удаления всегда применяется только блокирование.

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

Модель данных для иллюстрации примеров работы с событиями отслеживания изменений#

Далее примеры будут базироваться на следующей модели предметной области:

<?xml version="1.0" encoding="UTF-8" ?>
<model model-name="ChangeEventsModel" version="DEV-SNAPSHOT" xmlns="DataspaceModel">
    <!-- Внешний тип -->
    <external-types>
        <external-type type="Client" merge-kind="ORGANIZATION"/>
        <external-type type="Document" />
    </external-types>
    <!-- Корень агрегата -->
    <class name="AccountGroup" label="Группа счетов клиента — агрегат">
        <reference name="groupClient" type="Client" unique="true"/>
        <property name="accounts" type="Account" collection="set" mappedBy="accountGroup"/>
        <property name="statementInfo" type="StatementInfo" collection="set" mappedBy="accountGroup"/>
    </class>
    <!-- Отслеживаемая сущность для демонстрации примеров событий -->
    <class name="Account" label="Клиентский счет">
        <!-- Родительская ссылка на корень агрегата -->
        <property name="accountGroup" type="AccountGroup" parent="true"/>
        <!-- Свойство примитивного типа -->
        <property name="accountType" type="String" length="4" />
        <!-- Свойство примитивного типа -->
        <property name="number" type="String" length="32" unique="true"/>
         <!-- Embeddable свойство -->
        <property name="balance" type="Balance" historical="true"/>
        <!-- Ссылка на дочернюю сущность -->
        <property name="statementInfo" type="StatementInfo" />
        <!-- Ссылка на справочник -->
        <property name="branch" type="Branch" />
        <!-- Референс на внешнюю сущность  -->
        <reference name="client" type="Client"/>
        <!-- Свойство примитивного типа Text-->
        <property name="description" type="Text" />
        <!-- Свойство примитивного типа Binary-->
        <property name="hash" type="Binary" />
        <!-- Свойство с типом enum, имя которого совпадает с именем служебного атрибута события  -->
        <property name="status" type="StatusEnum" mandatory="true"/>
        <!-- Референс на другой агрегат  -->
        <reference name="product" type="Product" />
        <!-- Коллекция дочерних элементов -->
        <property name="postings" type="Posting" collection="set" mappedBy="account"/>
        <!-- Коллекция примитивного типа  -->
        <property name="tags" type="String" collection="set" />
        <!-- Коллекция внешних референсов   -->
        <reference name="documents" type="Document" collection="set"/>
        <!-- <property name="statusForAccounting" type="Status"/> будет создан при генерации DataSpace на основании статусной модели -->
    </class>
    <!-- Enum -->
    <enum name="StatusEnum">
        <value name="ACTIVE"/>
        <value name="INACTIVE"/>
    </enum>
    <!-- Embeddable -->
    <class name="Balance" embeddable="true">
        <property name="value" type="Decimal" length="20" scale="2"/>
        <property name="currency" type="String" length="3"/>
    </class>
    <!-- Справочник -->
    <class name="Branch" is-dictionary="true">
        <property name="code" type="String" />
        <property name="name" type="String" />
        <property name="location" type="String"/>
    </class>
    <!-- Дочерний класс  -->
    <class name="Posting" label="Движение по счету">
        <property name="account" type="Account" parent="true"/>
        <property name="amount" type="Decimal" />
        <property name="description" type="String" length="255"/>
    </class>
    <!-- Еще один дочерний класс -->
    <class name="StatementInfo" label="Данные для выписки">
        <property name="accountGroup" type="AccountGroup" parent="true"/>
        <property name="periodicity" type="Integer" />
        <property name="title" type="String" />
        <property name="name" type="String" />
        <property name="deliveryAddress" type="Text" />
    </class>
    <!-- Статусная модель -->
    <status-classes class="Account">
        <stakeholder name="Accounting" code="accounting" />
    </status-classes>
    <statuses class="Account">
        <stakeholder-link code="accounting">
            <status code="open" description="счет открыт без ограничений" name="открыт" initial="true">
                <to status="frozen"/>
                <to status="closed"/>
            </status>
            <status code="frozen" name="заблокирован">
                <to status="open"/>
                <to status="closed"/>
            </status>
            <status code="closed" name="закрыт"/>
        </stakeholder-link>
    </statuses>
    <!-- Отдельный агрегат -->
    <class name="Product" label="Продукт" lockable="true">
        <property name="name" type="String" label="Наименование"/>
        <property name="code" type="String" label="Код"/>
        <reference name="client" type="Client" label="Идентификатор клиента"/>
    </class>

    <event name="AccountChangeEvent" extends="BaseChangeEvent">
        <property name="account" type="Account" parent="true"/>
        <parents-property name="statusForAccounting"/>
        <parents-property name="client"/>
    </event>

    <event name="AccountObjectEvent" extends="BaseObjectEvent">
        <property name="account" type="Account" parent="true"/>
    </event>

    <event name="AccountTrackingEvent" extends="BaseTrackingEvent">
        <property name="account" type="Account" parent="true"/>
        <parents-property name="statusForAccounting.code"/> <!-- Примечание: сохраняется code статуса, отслеживается изменения идентификатора статуса -->
        <parents-property name="client"/>
        <parents-property name="statementInfo"/> <!-- Примечание: сохраняется и отслеживается значение ссылки -->
        <parents-property name="statementInfo.title"/> <!-- Примечание: дополнительно сохраняется значение свойства title сущности по ссылке statementInfoChildRef (если ссылка не `null`) -->
    </event>

    <event name="AccountSnapshotEvent" extends="BaseSnapshotEvent" snapshot-large-properties="true"> <!-- Примечание: у события задан атрибут snapshot-large-properties="true", т.е. в данных события будут сохранены значения свойств description c типом Text и hash с типом Binary-->
        <property name="account" type="Account" parent="true"/>
        <parents-property name="status" rename="accountStatus"/> <!-- Примечание: требуется явное переименование, поскольку status пересекается с именем служебного свойства события) -->
        <parents-property name="statementInfo.title"/> <!-- Примечание: дополнительно сохраняется значение свойства title сущности по ссылке statementInfoChildRef (если ссылка не `null`) -->
    </event>

</model>

Элемент parents-property#

Для указания отслеживаемых свойств существует специальный элемент в модели — parents-property со следующими атрибутами:

Имя атрибута

Назначение

name

а) Имя отслеживаемого свойства в указанном родительском классе или
б) путь к свойству сущности по ссылке, при необходимости сохранять в данных события значение этого свойства на момент создания события.
В случае, если событие сохраняет состояние отслеживаемой сущности, то указанные свойства переносятся в результирующее автоматическое событие с состоянием как есть, т.е. при указании ссылки — будет полноценная ссылка, при указании embeddable — полноценное embeddable со всеми его свойствами и т.д.
Однако, если указывается путь к свойству сущности по ссылке или к свойству embeddable типа, то отслеживаемым будет значение ссылки или embeddable свойства, а сохраняться будет значение свойства по указанному пути.
Доступ к свойствам сущности по ссылке имеет смысл только для событий, сохраняющих состояние. Если значение какого-либо свойства в пути равно null, то итоговое значение будет null.

rename

Используется в событиях, сохраняющих состояние изменившейся сущности, если при сохранении необходимо переименовать родительское свойство или свойство сущности по ссылке (например, при коллизии имен).
Если переименование для свойств сущности по ссылке или embeddable не задано, то в событии будет создано свойство с тем же именем.

Различные варианты задания parents-property иллюстрирует пример ниже, в котором создается дочернее событие ParentsPropertiesSample, унаследованное от BaseTrackingEvent. Его элементы parents-property демонстрируют способы объявления свойств родительского класса.

    <event name="ParentsPropertiesSample" extends="BaseTrackingEvent">
        <property name="account" type="Account" parent="true"/>
        <!-- указание на свойство-статус statusForAccounting -->
        <parents-property name="statusForAccounting"/>
        <!-- указание на примитивное свойство number — в результирующем классе события будет создано примитивное свойство number -->
        <parents-property name="number" />
        <!-- указание на ссылку на справочник branch — в результирующем классе события будет создано свойство-ссылка на справочник Branch -->
        <parents-property name="branch" />
        <!-- указание на примитивное свойство code справочника Branch — в результирующем классе события будет создано примитивное свойство branchCode -->
        <parents-property name="branch.code" rename="branchCode" />
        <!-- указание на свойство-перечисление status, переименование необходимо, поскольку имя совпадает с именем служебного свойства события — в результирующем классе события будет создано примитивное свойство accountStatus -->
        <parents-property name="status" rename="accountStatus" />
        <!-- указание на свойство-reference product — в результирующем классе события будет создано свойство-reference -->
        <parents-property name="product" />
        <!-- указание на embeddable-свойство balance целиком — в результирующем классе события свойства будет создано такое же embeddable свойство -->
        <parents-property name="balance" />
        <!-- указание на примитивное поле value у свойства balance с типом embeddable — в результирующем классе события будет создано примитивное свойство value -->
        <parents-property name="balance.value" />
        <!-- указание на свойство-ссылку statementInfo — в результирующем классе события будет создано свойство-ссылка -->
        <parents-property name="statementInfo" />
        <!-- указание на примитивное свойство name у свойства statementInfo — в результирующем классе события будет создано примитивное свойство infoName -->
        <parents-property name="statementInfo.name" rename="infoName" />
    </event>

BaseChangeEvent#

При объявлении для сущности дочернего события, унаследованного от BaseChangeEvent, событие указанного типа будет формироваться при изменении любого из свойств сущности из списка parents-property (и только в этом случае). Значения свойств отслеживаемой сущности в данных события не сохраняются, элементы parents-property задаются только для отслеживания изменений.

Собственные свойства BaseChangeEvent:

Свойство

Тип

Описание

sysVersion

Long

Версия сущности (ее агрегата) по результатам операции

sysTimeChanged

OffsetDateTime

Метка времени изменения, одинакова для всех событий в транзакции и совпадает с меткой времени изменения агрегата

Пример объявления BaseChangeEvent события, формируемого при изменении любого из свойств statusForAccounting, product:

<event name="AccountChangeEvent" extends="BaseChangeEvent">
  <property name="account" type="Account" parent="true"/>
  <parents-property name="statusForAccounting"/>
  <parents-property name="product"/>
</event>

BaseObjectEvent#

При объявлении для сущности дочернего события, унаследованного от BaseObjectEvent, событие указанного типа будет формироваться при изменении любого из свойств сущности (включая изменение коллекций примитивов и референсов), а также создании и удалении объекта. Эти события не хранят состояния отслеживаемой сущности. Для данного типа запрещено явное указание элементов parents-property, т.к. это не несет смысла.

Внимание!

Коллекции ссылок с типом связи «один-ко-многим» и mapped-by ссылки с типом связи один-к-одному не отслеживаются ни одним из типов событий.

Внимание!

При использовании данного вида события следует учитывать особенности отслеживания изменений сущностей при выполнении пакета команд Packet (см. раздел «Особенности отслеживания изменений сущностей при выполнении пакета команд Packet» документа «Руководство прикладного разработчика»).

В модели данных может быть только одно событие BaseObjectEvent для каждого пользовательского типа.

Собственные свойства BaseObjectEvent:

Свойство

Тип

Описание

sysVersion

Long

Версия сущности (ее агрегата) по результатам операции

sysTimeChanged

OffsetDateTime

Метка времени изменения. Одинакова для всех событий в транзакции и совпадает с меткой времени изменения агрегата

sysObjectEvent

enum SysObjectEvent

Тип действия, совершенного над отслеживаемой сущностью: C— create, U— update, D— delete

Пример объявления BaseObjectEvent события, формируемого при изменении любого из свойств родительского класса Account, кроме postings, при создании и удалении объектов типа Account.

<event name="AccountObjectEvent" extends="BaseObjectEvent">
  <property name="account" type="Account" parent="true"/>
</event>

BaseTrackingEvent#

При объявлении для сущности дочернего события, унаследованного от BaseTrackingEvent, событие указанного типа будет формироваться при изменении любого из перечисленных в parents-property свойств сущности, а также создании и удалении объекта. Значения указанных при помощи элементов parents-property свойств родительской сущности по состоянию на момент завершения операции сохраняются в копии этих свойств в данных события. При удалении сущности сохраняются значения, которые эти свойства имели непосредственно перед удалением. Доступна возможность сохранения свойств сущностей по ссылке, а также переименования сохраняемых свойств.

Внимание!

Элементы parents-property типов BaseTrackingEvent не могут указывать на коллекционные свойства.

Собственные свойства BaseTrackingEvent:

Свойство

Тип

Описание

sysVersion

Long

Версия сущности (ее агрегата) по результатам операции

sysTimeChanged

OffsetDateTime

Метка времени изменения. Одинакова для всех событий в транзакции и совпадает с меткой времени изменения агрегата

sysObjectEvent

enum SysObjectEvent

Тип действия, совершенного над отслеживаемой сущностью: C— create, U— update, D— delete

sysChangeUser

String

Информация о пользователе, изменившем данные, используется значение из HTTP-заголовка (конфигурирование способа получения информации описано в разделе «Способы получения информации о пользователе» документа «Руководство по системному администрированию»)

При изменении атрибутного состава родительского класса (например, в родительском классе добавили или удалили атрибут, или изменили тип, или изменился признак deprecated) класс события также обновится соответствующим образом.

Пример объявления BaseTrackingEvent события, формируемого при изменении любого из свойств statusForAccounting, description, statementInfo, а также при создании и удалении объектов:

<event name="AccountTrackingEvent" extends="BaseTrackingEvent">
    <property name="account" type="Account" parent="true"/>
    <!-- Сохраняется code статуса, отслеживается изменения идентификатора статуса -->
    <parents-property name="statusForAccounting.code"/>
    <parents-property name="description"/>
    <!-- Сохраняется и отслеживается значение ссылки -->
    <parents-property name="statementInfo"/>
    <!-- Дополнительно сохраняется значение свойства сущности по ссылке (если ссылка не `null`) -->
    <parents-property name="statementInfo.title"/>
</event>

BaseSnapshotEvent#

При объявлении для сущности дочернего события, унаследованного от BaseSnapshotEvent, событие указанного типа будет формироваться при изменении любого из свойств сущности (включая изменение коллекций примитивов и референсов), а также создании и удалении объекта. Это событие сохраняет в своих данных состояние всех свойств по состоянию на момент завершения операции, за исключением коллекций и свойств с типами Text и Binary (то есть в классе события будут созданы соответствующие свойства). При удалении сущности сохраняются значения, которые эти свойства имели непосредственно перед удалением. Помимо этого, через элементы parents-property доступна возможность сохранения свойств сущностей по ссылке, а также переименования сохраняемых свойств. Если необходимо сохранять и свойства с типами Text и Binary, то следует явно указать имена нужных свойств при помощи элемента parents-property. Также имеется возможность сохранять значения всех свойств с типами Text и Binary, задав на элементе event события атрибут snapshot-large-properties="true".

Внимание!

Элементы parents-property типов BaseSnapshotEvent не могут указывать на коллекционные свойства.

Внимание!

Следует учесть, что данные свойств с типами Text и Binary могут занимать значительное место. Поэтому в событии следует сохранять только то, что действительно необходимо фиксировать на момент транзакции (что нельзя, например, получить при помощи GraphQL-query при публикации).

Внимание!

При использовании данного вида события следует учитывать особенности отслеживания изменений сущностей при выполнении пакета команд Packet (см. раздел «Особенности отслеживания изменений сущностей при выполнении пакета команд Packet» документа «Руководство прикладного разработчика»).

Состав собственных атрибутов BaseSnapshotEvent совпадает с BaseTrackingEvent.

При изменении атрибутного состава родительского класса (например, в родительском классе добавили или удалили атрибут, или изменили тип, или изменился признак deprecated) класс события также соответствующим образом изменится.

Пример объявления BaseSnapshotEvent события, формируемого при изменении любого из свойств parent класса, кроме postings, а также при создании и удалении объектов:

<event name="AccountSnapshotEvent" extends="BaseSnapshotEvent" snapshot-large-properties="true"> <!-- Примечание: включен snapshot-large-properties, т.е. сохраняются и свойства `someText`, `someBinary` -->
    <property name="account" type="Account" parent="true"/>
    <!-- Дополнительно сохраняется значение свойства сущности по ссылке (если ссылка не `null`) -->
    <parents-property name="statementInfo.title"/>
    <!-- Необходимо явное переименование, поскольку status пересекается с именем служебного свойства события) -->
    <parents-property name="status" rename="accountStatus"/>
</event>

Отслеживание состояния очереди подписок#

Для отслеживания состояния очереди подписок необходимо воспользоваться функционалом пользовательских sql запросов и сформировать в своей модели необходимые запросы к таблице очереди обработки событий t_dspc_sys_event_queue_item. Примеры таких запросов можно найти в разделе «Примеры запросов для контроля очереди событий модуля подписок».