Создание карточки-сателлита
Создание карточки-сателлита¶
Карточка-сателлит - это специальная карточка, которая прозрачно для пользователя сопровождает основную карточку, т.е. пользователь явно не создаёт и не удаляет сателлит, и даже не подозревает о его существовании. Например, карточка с настройками сотрудника, которая позволяет соотнести с каждым сотрудником его настройки рабочего места, при этом не изменяя внешний вид и структуру основной карточки сотрудника.
Сателлит даёт следующие преимущества:
-
Можно изменять связанные с карточкой данные, не изменяя версию карточки.
-
Можно выполнять параллельное изменение данных (например, при параллельном согласовании), не блокируя основную карточку.
-
Можно связать данные с типом карточки, не изменяя его структуру. Это позволяет иметь нестандартное API (такое, как ролевая модель), которое продолжит корректно взаимодействовать с основной карточкой.
-
Неизменность структуры основной карточки также обеспечивает бинарную совместимость этой карточки. Т.е. ранее удалённые или экспортированные карточки без сателлита по-прежнему можно будет восстановить.
Для карточки-сателлита необходимо обеспечить:
-
Создание по первому требованию со стороны расширений. Это может быть старт бизнес-процесса или явный запрос настроек сотрудника при старте приложения.
-
Загрузка по идентификатору основной карточки. Писатели расширений должны легко получить данные сателлита как на клиенте, так и на сервере, зная только идентификатор основной карточки.
-
Автоматическое удаление при удалении основной карточки.
-
Автоматический экспорт при экспорте основной карточки.
-
Автоматический импорт при импорте основной карточки.
-
Восстановление из корзины вместе с восстановлением основной карточки.
Для упрощения разработки сателлитов карточек в системе предусмотрен механизм универсальных сателлитов, который уже обеспечивает все вышеописанные требования к сателлитам, а также позволяет их расширять с помощью дополнительно реализованного обработчика сателлитов.
Универсальные сателлиты¶
Механизм универсальных сателлитов состоит из 3 основных объектов:
-
ISatelliteTypeRegistry
- объект, в котором регистрируются новые типы сателлитов. Он реализован в платформе. -
SatelliteTypeDescriptor
- дескриптор типа сателлита. Содержит настройки типа сателлита. Создается отдельно для каждого типа сателлита. -
ISatelliteHandler
- обработчик сателлита, в котором реализуется дополнительная логика обработки сателлита. Может создаваться для как отдельно для каждого типа сателлита, так и в нескольких типах сателлита.
Дескриптор типа сателлита SatelliteTypeDescriptor
имеет следующие свойства:
-
IsSingleton - данный флаг определяет, должен ли данный тип сателлита быть синглтоном по отношению к основной карточке или к заданию, если данный тип сателлита относится к заданию карточки. Когда для типа сателлита установлен этот флаг, а у карточки уже есть сателлит с данным типом, то при попытке создать новый сателлит будет возвращена ошибка.
-
IsDeferredStore - данный флаг определяет, будет ли сателлит автоматически сохранен в базе при его первой загрузке. Если флаг не установлен, то при попытке получить карточку сателлита, если сателлита данного типа еще нет, он будет автоматически создан и сохранен. Если флаг установлен - то только создан.
-
IsTaskSatellite - флаг определяет, отноится ли сателлит к самой карточке или к конкретному заданию карточки.
-
AllowGetFromClient - флаг определяет, доступна ли загрузка сателлита с клиента.
-
AllowDeleteFromClient - флаг определяет, доступно ли удаление сателлита с клиента.
-
LoadMainCardFiles - флаг определяет, что при загрузке данного сателлита к нему будут добавлены на чтение все файлы основной карточки. Обычно не устанавливается без флага AllowGetFromClient.
-
IgnoreStoreExtensions - флаг определяет, что для сателлита с данным типом не применяются стандартные расширения на сохранение для сателлитов.
-
IgnoreGetPrepare - флаг определяет, что при загрузке сателлита не будут производиться методы подготовки сателлита по основной карточке. Это означает, что будут проигнорирован флаг LoadMainCardFiles в настройках дескриптора, а также логика работы методов PrepareSatelliteForGetAsync и GetExternalFileSourcesAsync в хендлере данного типа сателлита.
-
CopySatelliteOnCardCopy - флаг определяет, должен ли сателлит копироваться вместе с основной карточкой.
-
HandlerType - тип обработчика, который будет использоваться в расширениях для данного типа сателлита. Методы, которые можно переопределить обработчике сателлита, описаны ниже.
Обработчик сателлита ISatelliteHandler
имеет следующие методы, которые можно переопределить:
-
IsMainCardTypeAsync - метод для проверки, является ли тип основной карточки (для которой создается сателлит) типом, который может иметь данный сателлит.
-
GetExternalFileSourcesAsync - метод для получения списка пар “идентификатор карточки”-“идентификатор типа карточки”, файлы которых добавляются в данный сателлит при его загрузке. Логика данного метода игнорируется, если в дескрипторе типа сателлита установлен флаг IgnoreGetPrepare.
-
SetupSatelliteFileAsync - метод для фильтрации и подготовки карточек файлов, которые были добавлены из основной карточки (при наличии флага LoadMainCardFiles в дескрипторе типа сателлита) или из карточек, которые вернул метод GetExternalFileSourcesAsync. В данном методе можно отфильтровать файлы, которые не должны быть переданы в сателлит, или изменить свойства файлов.
-
IsMainCardFileAsync - метод для определения, является ли данный файл - файлом основной карточки. При сохранении карточки сателлита с файлом, если файл относится к основной карточке, файл будет добавлен к основной карточке, а не карточке сателлита. По умолчанию для всех файлов возвращает
false
. -
PrepareMainCardFileToStoreAsync - метод для подготовки сохранения файла в основную карточку при сохранении карточки сателлита. Вызывается для тех файлов, для которых метод IsMainCardFileAsync вернул
true
. -
PrepareSatelliteForGetAsync - метод для подготовки карточки сателлита при его загрузке. В нем можно производить заполнение виртуальных секций карточки сателлита с использованием основной карточки. Данный метод выполняется после добавления файлов из основной карточки/других карточек, поэтому в нем также можно отфильтровать данные файлы или измеить их свойства. Логика данного метода игнорируется, если в дескрипторе типа сателлита установлен флаг IgnoreGetPrepare.
-
PrepareSatelliteForBackupAsync - метод для подготовки карточки сателлита при удалении основной карточки в корзину.
-
PrepareSatelliteForExportAsync - метод для подготовки карточки сателлита при экспорте основной карточки.
-
PrepareSatelliteForCreateAsync - метод для подготовки карточки сателлита при ее создании.
-
CheckFileAccessAsync - метод для проверки доступа к содержимому файла, когда содержимое загружается из карточки сателлита.
-
CheckFileVersionsAccessAsync - метод для првоерки доступа к списку версий файла, когда список загружается из карточки сателлита.
-
PrepareSatelliteForImportAsync - метод для подготовки карточки сателлита при импорте основной карточки.
-
PrepareSatelliteForDeleteAsync - метод для подготовки карточки сателлита при удалении основной карточки.
-
PrepareSatelliteForRestoreAsync - метод для подготовки карточки сателлита при восстановлении основной карточки из корзины.
-
PrepareSatelliteForRepareAsync - метод для починки карточки сателлита, который вызывается при починке основной карточки.
Создание нового типа сателлита¶
Чтобы создать новый тип сателлита нужно:
-
В свой тип карточки, который необходимо сделать сателлитом, добавить секцию Satellites вместе с колонками MainCard, Type и, если сателлит должен относится не к самой карточке, а к некому заданию, то также необходимо добавить колонку Task.
-
Необходимо создать объект с классом
SatelliteTypeDescriptor
с указанием идентификатора необходимого типа карточки, а также задать необходимые свойства, определяющие поведение при работе сателлита:new SatelliteTypeDescriptor(DefaultCardTypes.KrSatelliteTypeID) { HandlerType = typeof(KrSatelliteHandler), IsSingleton = true, IgnoreGetPrepare = true, }
-
В регистраторе в методе
FinalizeRegistration
необходимо зарезолвить объектISatelliteTypeRegistry
и зарегистрировать в нем через методRegister
объект дескриптора типа сателлита, созданный в предыдущем пункте:var registry = this.UnityContainer.Resolve<ISatelliteTypeRegistry>(); registry.Register(new SatelliteTypeDescriptor(DefaultCardTypes.KrSatelliteTypeID) { HandlerType = typeof(KrSatelliteHandler), IsSingleton = true, IgnoreGetPrepare = true, });
registry.Register(new SatelliteTypeDescriptor(DefaultCardTypes.KrSecondarySatelliteTypeID) { HandlerType = typeof(KrSecondarySatelliteHandler), IgnoreGetPrepare = true, });
-
Если для типа сателлита необходимо реализовать дополнительное поведение, то нужно создать свой тип, который реализует интерфейс
ISatelliteHandler
, зарегистрировать его в Unity и указать данный тип в качестве значения для свойстваHandlerType
в объект дескриптора типа сателлита. Для удобства можно наследоваться от классаSatelliteHandlerBase
:public sealed class WfSatelliteHandler : SatelliteHandlerBase { #region Fields
private readonly IKrTypesCache krTypesCache;
#endregion
#region Constructors
public WfSatelliteHandler(IKrTypesCache krTypesCache) { this.krTypesCache = krTypesCache; }
#endregion
#region Base Overrides
public override ValueTask<bool> IsMainCardTypeAsync(CardType mainCardType, CancellationToken cancellationToken = default) { return WfHelper.TypeSupportsWorkflowAsync(this.krTypesCache, mainCardType, cancellationToken); }
#endregion } ..... public override void RegisterUnity() { this.UnityContainer .RegisterType<WfSatelliteHandler>(new ContainerControlledLifetimeManager()) ; }
Автоматические сателлиты¶
В системе есть возможность создавать карточки сателлитов без использования каких-либо расширений.
Для этого достаточно в тип карточки добавить секцию Satellites вместе с колонками MainCard, Type. Система будет использовать данный тип карточки как сателлит с настройками, которые указаны в дескрипторе SatelliteTypeDescriptor.AutoSatelliteType
.
Это позволяет легко сделать карточки-сателлиты без особой логики, или логикой, реализованной собственными расширениями, которые при этом автоматически будут экспортироваться, импортироваться, удаляться, удаляться в корзину и восстанавливаться вместе с основной карточкой.