Синхронизация bpm'online с внешними хранилищами данных
Glossary Item Box
Общая информация
В bpm’online реализован механизм синхронизации с внешними хранилищами данных (Sync Engine) который позволяет создавать, изменять и удалять Entity в системе на основании данных из внешних систем и экспортировать данные во внешние системы.
Процесс синхронизации осуществляется с помощью класса SyncAgent, который реализован в пространстве имен Terrasoft.Sync ядра приложения.
Классы, задействованные в механизме синхронизации
- Агент синхронизации (SyncAgent) — класс с одним публичным методом Synchronize, который запускает синхронизацию между переданными ему хранилищами данных.
- Контекст синхронизации (SyncContext) — класс, представляющий собой агрегацию провайдеров и метаданных для работы SyncAgent.
- Хранилище — конкретный репозиторий синхронизируемых данных.
- Локальное хранилище (LocalProvider) — позволяет работать с LocalItem в bpm’online.
- Внешнее хранилище (RemoteProvider) — внешний сервис или приложение, данные из которого синхронизируются с bpm’online.
- Элемент синхронизации (SyncItem) — множество объектов из внешнего и локального хранилища, между которыми устанавливается однозначное соответствие.
- Элемент синхронизации внешнего хранилища (RemoteItem) — представляет набор данных из внешнего хранилища, который синхронизируется атомарно. Может состоять из одной или нескольких сущностей (записей) внешнего хранилища.
- Элемент синхронизации (SyncEntity) — является оберткой над конкретными Entity. SyncEntity необходим для работы с Entity как c синхронизируемым объектом, так и с состоянием и действием, которое с этим Entity необходимо произвести (добавить, удалить, изменить).
- Элемент синхронизации (LocalItem) — один или несколько объектов из bpm’online, которые синхронизируются с внешним хранилищем как одно целое. Элемент синхронизации из внешнего хранилища, конвертированный в сущности LocalItem, в свою очередь, содержит набор экземпляров класса SyncEntity.
- Таблица метаданных SysSyncMetadata — содержит служебную информацию синхронизируемых элементов, по сути является таблицей развязки RemoteItem-LocalItem. Описание метаданных можно посмотреть в статье "Описание работы с метаданными для синхронизации".
Общий алгоритм синхронизации
Перед началом синхронизации необходимо создать экземпляр SyncAgent и контекст синхронизации SyncContext, после этого актуализировать записи в таблице метаданных данными из bpm’online. Для этого нужно вызвать метод CollectChangesInSyncedEntities класса, реализующего интерфейс IReplicaMetadata.
Общий алгоритм актуализации записей метаданных следующий:
- Если какая-либо ранее синхронизированная сущность в bpm’online была изменена с момента последней синхронизации, значит у соответствующей записи в метаданных изменяется дата модификации, свойству LocalState устанавливается значение “Изменен”, а в качестве источника модификации устанавливается идентификатор LocalStore.
- Если синхронизированная сущность в bpm’online была удалена после последней синхронизации — у соответствующей записи в метаданных устанавливается LocalState “Удален".
- Если для сущности в bpm’online нет соответствующей записи в метаданных — она игнорируется.
Далее начинается процесс синхронизации хранилищ:
- Поочередно запрашиваются все изменения из внешнего хранилища.
- Для каждого элемента внешнего хранилища необходимо получить метаданные.
- Если метаданные получить не удалось — это новый элемент, который конвертируется в элемент bpm’online и сохраняется. Для заполнения объекта синхронизации, в приложении вызывается метод FillLocalItem у конкретного экземпляра RemoteItem. Также сохраняется запись в метаданных (Id внешнего хранилища, Id элемента во внешнем хранилище, дата создания и модификации устанавливается текущей, источник создания и модификации — внешнее хранилище).
- Если получены метаданные, значит, этот элемент уже был синхронизирован с bpm’online. Необходимо перейти к решению конфликта версий. По умолчанию приоритет имеют последние изменения в приложении или внешнем хранилище (реализация в RemoteProvider).
- Актуализируются метаданные для текущей пары элементов синхронизации.
После перебора всех измененных элементов из внешнего хранилища, в метаданных (в интервале между прошлой и текущей синхронизациями) остались элементы, которые были изменены в bpm’online, но не были изменены во внешнем хранилище.
- Необходимо получить измененные в bpm’online элементы в промежутке между прошлой синхронизацией и началом текущей синхронизации.
- Применяются изменения во внешнем хранилище.
- Необходимо обновить дату модификации элементов в метаданных (источник изменения bpm’online).
После этого необходимо новые, еще не синхронизированные записи из bpm’online добавить во внешнее хранилище, а также добавить метаданные для новых элементов.
Контекст синхронизации
Класс SyncContext
Класс, представляющий собой агрегацию провайдеров и метаданных для работы SyncAgent. Свойства класса SyncContext представлены в таблице 1.
Табл. 1. — Свойства класса SyncContext
Поле | Тип | Назначение |
---|---|---|
Logger | ISyncLogger | Объект, который позволяет сохранять сообщения в лог интеграции. |
LocalProvider | LocalProvider | Позволяет работать с LocalItem. |
RemoteProvider | RemoteProvider | Внешний сервис или приложение, данные из которого синхронизируются с bpm'online. |
ReplicaMetadata | IReplicaMetadata | Реализует работу с метаданными. |
LastSyncVersion | DateTime | Дата и время последней синхронизации в UTC. |
CurrentSyncStartVersion | DateTime | Текущие дата и время синхронизации в UTC. Устанавливается после обновления метаданных. |
Что необходимо реализовать для синхронизации с любым внешним хранилищем
Внешнее хранилище
Внешнее хранилище (RemoteProvider) — инкапсулирует работу с данными из внешнего хранилища.
RemoteProvider — базовый класс, реализующий работу с внешним хранилищем. По сути, единая точка работы с внешней системой. На данный момент его реализация дает много свободы в реализации внешнего провайдера. Свойства класса RemoteProvider представлены в таблице 2, а методы — в таблице 3.
Табл. 2. — Свойства класса RemoteProvider
Поле | Тип | Описание |
---|---|---|
StoreId | Guid | Идентификатор внешнего хранилища, с которым будет происходить синхронизация. |
Version | DateTime | Дата и время последней синхронизации. |
SyncItemSchemaCollection | List<SyncItemSchema> | Схемы элементов внешнего хранилища. |
RemoteChangesCount | Int | Количество элементов, обработанных из внешнего хранилища. |
LocalChangesCount | Int | Количество элементов, обработанных из локального хранилища. |
Табл. 3. — Методы класса RemoteProvider
Метод | Тип возвращаемого значения | Описание |
---|---|---|
KnownTypes() | IEnumerable<Type> | Возвращает коллекцию всех типов, реализующих интерфейс IRemoteItem. SyncAgent строит на их основе экземпляры SyncItemSchema, которые описывают сущности, участвующие в синхронизации. |
ApplyChanges(SyncContext context, IRemoteItem synItem) | Void | Применяет изменения в элементе внешнего хранилища. |
CommitChanges(SyncContext context) | Void | Вызывается после обработки изменений во внешнем и локальном хранилище. Предназначен для реализации необходимых дополнительных действий для конкретной реализации интеграции. |
EnumerateChanges(SyncContext context) | IEnumerable<IRemoteItem> | Возвращает перечисление новых и измененных элементов внешнего хранилища. |
LoadSyncItem(SyncItemSchema schema, string id) | IRemoteItem | Заполняет экземпляр IRemoteItem данными из внешнего хранилища. |
CreateNewSyncItem(SyncItemSchema schema) | IRemoteItem | Cоздает новый экземпляр IRemoteItem. |
CollectNewItems(SyncContext context) | IEnumerable<LocalItem> | Возвращает перечисление новых сущностей bpm'online, которые будут синхронизированы во внешнее хранилище. |
ResolveConflict(IRemoveItem syncItem, ItemMetadata itemMetaData, Guid localStoreId) | SyncConflictResolution | Разрешает конфликт между измененными элементами локального и внешнего хранилища. По умолчанию (реализация в RemoteProvider) приоритет имеют изменения в bpm’online. |
NeedMetaDataActualization() | Boolean | Возвращает признак необходимости актуализации метаданных до начала синхронизации. |
GetLocallyModifiedItemsMetadata(SyncContext context, EntitySchemaQuery modifiedItemsEsq) | IEnumerable<ItemMetadata> | Возвращает элементы синхронизации, измененные в локальном хранилище после последней синхронизации. |
Интерфейс IRemoteItem
Класс, реализующий интерфейс IRemoteItem, является неделимой единицей синхронизации и представляет собой один элемент синхронизации из внешнего хранилища данных. Класс одновременно является контейнером для данных, приходящих из внешней системы, и сам знает, как преобразовывать эти данные в сущности Entity, и наоборот — из Entity наполнить себя. Интерфейс содержит два метода, FillLocalItem и FillRemoteItem для конвертации внешнего элемента синхронизации (RemoteItem, то есть себя) в LocalItem и наоборот. Методы интерфейса представлены в таблице 4.
Табл. 4. — Методы интерфейса IRemoteItem
Метод | Тип возвращаемого значения | Описание |
---|---|---|
FillLocalItem(SyncContext context, ref LocalItem localItem) | Void | Заполняет свойства элемента локального хранилища LocalItem значениями элемента внешнего хранилища. Используется для применения изменений в локальном хранилище. |
FillRemoteItem(SyncContext context, ref LocalItem localItem) | Void | Заполняет свойства элемента внешнего хранилища значениями из элемента локального хранилища LocalItem. Используется для применения изменений во внешнем хранилище. |
Атрибут Map
Атрибутом Map декорируются реализации интерфейса IRemoteItem. Основным параметром атрибута является SchemaName. Это название той EntitySchema, которая участвует в текущем элементе синхронизации:
[Map("Activity", 0)] [Map("ActivityParticipant", 1)] public class GoogleTask: IRemoteItem { . . .
В таком объявлении класса задача из календаря Google будет синхронизироваться с активностью и участниками активности из bpm’online.
Второй параметр Order определяет в каком порядке Entity будут сохранены в локальном хранилище. Activity указывается первой, т.к. ActivityParticipant хранит ссылку на создаваемую активность и при другом порядке будет вызвано исключение.
В большинстве случаев SyncAgent может автоматически сформировать запрос по выборке новых элементов синхронизации из bpm’online. Для этого необходимо указать основную сущность и способ связи с деталями:
[Map("Activity", 0, IsPrimarySchema = true)] [Map("ActivityParticipant", 1, PrimarySchemaName = "Activity", ForeingKeyColumnName = "Activity")] public class GoogleTask: IRemoteItem { . . .
В данном случае в БД отправится один запрос на получение новых активностей и по одному запросу на каждую выбранную активность для получения связанных с ней участников. Список свойств атрибута представлен в таблице 5.
Табл. 5. — Свойства атрибута Map
Параметр | Тип | Описание |
---|---|---|
SchemaName | String | Название схемы объекта. |
Order | Int | Порядок обработки сущности для элемента синхронизации. |
IsPrimarySchema | Boolean | Флаг, указывающий, что данная схема является основной в данном элементе синхронизации. Может быть установлен только у одной схемы. |
PrimarySchemaName | String | Имя схемы главного объекта. Не может указываться в паре с IsPrimarySchema. |
ForeignKeyColumnName | String |
Имя колонки для связи детали с главным объектом. Не может указываться в паре с IsPrimarySchema. |
Direction | SyncDirection |
Определяет направление синхронизации для объектов текущего типа. Значение по умолчанию — DownloadAndUpload. Если не содержит флаг Download — изменения не будут применять в bpm'online. Если не содержит флаг Upload — не будут выбираться новые сущности из bpm'online. |
FetchColumnNames | String[] | Названия колонок, которые будут загружаться из локального хранилища. |
Локальное хранилище
Локальное хранилище (LocalProvider) — инкапсулирует работу с данными во внутреннем хранилище (bpm'online).
LocalProvider — базовый класс, реализующий работу с локальным хранилищем. Позволяет работать с LocalItem в bpm'online. Методы данного класса являются неизменными, а их перечень представлен в таблице 6.
Табл. 6. — Методы класса LocalProvider
Метод | Тип возвращаемого значения | Описание |
---|---|---|
AddItemSchemaColumns(EntitySchemaQuery esqForFetching, EntityConfig entityConfig) | Void | Добавляет в EntitySchemaQuery колонки, указанные в EntityConfig. |
ApplyChanges(SyncContext context, LocalItem entities) | Void | Применяет изменения к каждому SyncEntity в LocalItem. |
FetchItem(ItemMetadata itemMetaData, SyncItemSchema itemSchema, bool loadAllColumns = false) | LocalItem | Загружает колекцию сущностей, связанных с конкретным элементом синхронизации. |
Класс SyncEntity
Класс SyncEntity инкапсулирует экземпляр Entity и все необходимые для выполнения действий синхронизации этого экземпляра свойства. Свойства класса представлены в таблице 7.
Табл. 7. — Свойства класса SyncEntity
Параметр | Тип | Описание |
---|---|---|
EntitySchemaName | String | Название схемы, для которой создается обертка. |
Entity | Entity | Entity, для которой создается обертка. |
State | SyncState | Последнее действие, произведенное над entity (0 — не изменено, 1 — новое, 2 — изменено, 3 — удалено) |
Класс SyncItemSchema
Схема настройки сущности элемента синхронизации. Свойства класса представлены в таблице 8, а методы — в таблице 9.
Табл. 8. — Свойства класса SyncItemSchema
Параметр | Тип | Описание |
---|---|---|
SyncValueName | String | Название типа сущности. |
SyncValueType | Type | Тип сущности. |
PrimaryEntityConfig | EntityConfig | Настройка основной сущности элемента синхронизации. |
Configs | List<EntityConfig> | Список настроек сущностей элемента синхронизации. |
DetailConfigs | List<DetailEntityConfig> | Список настроек сущностей деталей элемента синхронизации |
Direction | SyncDirection |
Определяет направление синхронизации для объектов текущего типа. Значение по умолчанию — DownloadAndUpload. Если не содержит флаг Download — изменения не будут применяться в bpm’online. Если не содержит флаг Upload — не будут выбираться новые сущности из bpm’online. |
Табл. 9. — Методы класса SyncItemSchema
Метод | Тип возвращаемого значения | Описание |
---|---|---|
CreateSyncItemSchema(Type syncValueType) | SyncItemSchema | Создает настройки сущности элемента синхронизации со всеми настройками связанных сущностей. |
Validate(UserConnection userConnection) | Void |
Метод проверяет правильность сформированного EntityConfig. Если проверка не прошла — выдается исключение (в случае, если в EntityConfig имя схемы указано два раза — генерируется DublicateDataException, если указано имя несуществующей схемы — InvalidSyncItemSchemaException). |
FetchItem(ItemMetadata itemMetaData, SyncItemSchema itemSchema, bool loadAllColumns = false) | LocalItem | Загружает коллекцию сущностей, связанных с конкретным элементом синхронизации. |
Класс EntityConfig
Настройка сущностей элемента синхронизации. Свойства класса представлены в таблице 10.
Табл. 10. — Свойства класса EntityConfig
Параметр | Тип | Описание |
---|---|---|
SchemaName | String | Название схемы объекта. |
Order | Int | Порядок обработки сущности для элемента синхронизации. Чем меньше значение, тем раньше сущность будет обработана при обработке элемента синхронизации. |
Direction | SyncDirection |
Определяет направление синхронизации для объектов текущего типа. Значение по умолчанию — DownloadAndUpload. Если не содержит флаг Download — изменения не будут применяться в bpm’online. Если не содержит флаг Upload — не будут выбираться новые сущности из bpm’online. |
FetchColumnNames | String[] | Названия колонок, которые будут загружаться из локального хранилища. Если при создании экземпляра значение не указано, то будут загружаться все колонки объекта. |
Класс DetailEntityConfig
Настройка сущностей деталей элемента синхронизации.Свойства класса представлены в таблице 11.
Табл. 11. — Свойства класса DetailEntityConfig
Параметр | Тип | Описание |
---|---|---|
PrimarySchemaName | String | Имя схемы основной синхронизируемой сущности bpm'online. |
ForeignKeyColumnName | String | Имя колонки для связи детали с главным объектом. |
Класс LocalItem
Представляет собой один или несколько объектов из bpm’online, которые синхронизируются с внешним хранилищем как одно целое. Содержит набор экземпляров классов SyncEntity. Свойства класса представлены в таблице 12, а методы — в таблице 13.
Табл. 12. — Свойства класса LocalItem
Параметр | Тип | Описание |
---|---|---|
Entities | Dictionary<string, List<SyncEntity>> | Коллекция SyncEntity, которая ставится в соответствия с одним SyncItem. Содержит коллекцию пар "ключ-значение", где ключ — имя схемы, а значение — коллекция SyncEntity этой схемы. |
Version | DateTime | Наибольшее значение даты и времени модификации из всех Entities в LocalItem. |
Schema | SyncItemSchema | Схема настройки сущности элемента синхронизации. |
Табл. 13. — Методы класса LocalItem
Метод | Тип возвращаемого значения | Описание |
---|---|---|
AddOrReplace(string schemaName, SyncEntity syncEntity) | Void | Добавляет новый SyncEntity в колекцию. В случае если SyncEntity с таким EntityId уже существует, заменяет его. |
Add(UserConnection userConnection, string schemaName) | SyncEntity | Создает и добавляет новый SyncEntity в коллекцию. |
Пример синхронизации
Активность и ее участники синхронизируются в одну задачу Google-календаря. Активность (Activity) и ее участники (SyncEntity) являются одним элементом синхронизации — LocalItem.
RemoteItem — это задача Google, которую получили извне bpm'online. LocalItem – это набор объектов (SyncEntity), в которые в итоге конвертируется задача Google.
Схема синхронизации отображена на рисунке 1.
Рис. 1. — Схема синхронизации