Назначение хранилищ — логическое разделение информации, которая содержится в хранилище, и упрощение ее дальнейшего использования в исходном коде.
Действия, которые позволяют выполнять хранилища Creatio:
- Получить доступ к данным по ключу для чтения или записи.
- Удалить данные из хранилища по ключу.
Виды хранилищ
Виды хранилищ, которые поддерживает Creatio:
- Хранилище данных.
- Кэш.
Действия, которыми позволяет управлять разделение хранилищ:
- Изолировать данные между рабочими пространствами и сессиями пользователей.
- Условно классифицировать данные.
- Управлять временем жизни данных.
Физически хранилища данных и кэша могут располагаться на абстрактном сервере хранения данных. Исключением являются данные уровня Request, которые хранятся в памяти.
Сервером хранилища данных является Redis. В качестве сервера хранилищ может использоваться произвольное хранилище, доступ к которому осуществляется через унифицированные интерфейсы. Необходимо учитывать, что обращение к хранилищу является ресурсоемкой операцией, поскольку связана с сериализацией/десериализацией данных и сетевым обменом.
Хранилище данных
Назначение хранилища данных — промежуточное хранение редко изменяемых (т. е., долгосрочных) данных. Хранилище данных состоит из уровней, которые представлены в таблице ниже. Уровни хранилища представлены перечислением Terrasoft.Core.Store.DataLevel. Перечисление DataLevel описано в Библиотеке .NET классов.
Данные, которые добавляются в хранилище, хранятся в нем до момента явного удаления.
Хранилище кэша
Назначение хранилища кэша — хранение оперативной информации. Хранилище кэша состоит из уровней, которые представлены в таблице ниже. Уровни хранилища представлены перечислением Terrasoft.Core.Store.CacheLevel. Перечисление CacheLevel описано в Библиотеке .NET классов.
Данные, которые хранятся в кэше, характеризуются временем устаревания. Время устаревания — граничный срок актуальности элемента кэша. Независимо от времени устаревания, все элементы удаляются из кэша при завершении времени их жизни.
Данные можно удалить из кэша в произвольный момент времени. Поэтому могут возникать ситуации, когда исходный код пытается получить закэшированные данные, которые на момент обращения уже удалены. В этом случае необходимо получить данные из постоянного хранилища и поместить их в кэш.
Класс Terrasoft.Core.Entities.EntitySchemaQuery предоставляет механизм работы с хранилищем (кэшем Creatio или произвольным хранилищем, которое определено пользователем). Работа с кэшем позволяет оптимизировать эффективность выполнения операций путем обращения к закэшированным результатам запроса без дополнительного обращения к базе данных. При выполнении EntitySchemaQuery-запроса данные, которые получены из базы данных, добавляются в кэш (значение свойства Cache) с ключом (значение свойства CacheItemName). По умолчанию в качестве кэша EntitySchemaQuery-запроса выступает кэш Creatio уровня сессии с локальным хранением данных. В качестве кэша запроса можно использовать произвольное хранилище, которое реализует интерфейс ICacheStore.
Пример работы с кэшем приложения при выполнении запроса EntitySchemaQuery приведен ниже.
Объектная модель хранилищ
Логика работы с хранилищем данных и кэшем реализована в классах и интерфейсах пространства имен Terrasoft.Core.Store. Пространство имен описано в Библиотеке .NET классов.
Интерфейс IBaseStore
Назначение интерфейса Terrasoft.Core.Store.IBaseStore — определяет базовые возможности всех видов хранилищ.
Действия, которые позволяет реализовать интерфейс IBaseStore:
- Получить доступ к данным по ключу для чтения или записи (индексатор this[string key]).
- Удалить данные из хранилища по заданному ключу (метод Remove(string key)).
- Инициализировать хранилище заданным перечнем параметров (метод Initialize(IDictionary parameters)). Параметры для инициализации хранилищ Creatio считываются из конфигурационного файла. Перечень параметров задается в секциях storeDataAdapter (для хранилища данных) и storeCacheAdapter (для кэша). Можно задать параметры произвольным образом.
Интерфейс IDataStore
Назначение интерфейса Terrasoft.Core.Store.IDataStore — определяет специфику работы с хранилищами данных. Является наследником базового интерфейса хранилищ IBaseStore. Позволяет получить перечень всех ключей хранилища (свойство Keys).
Интерфейс ICacheStore
Назначение интерфейса Terrasoft.Core.Store.ICacheStore — определяет специфику работы с кэшем. Является наследником базового интерфейса хранилищ IBaseStore. Позволяет оптимизировать работу с хранилищем при одновременном получении набора данных. Реализует метод GetValues(IEnumerable keys), который возвращает словарь объектов кэша с заданными ключами.
Класс Store
Назначение статического класса Terrasoft.Core.Store.Store — получает доступ к кэшу и хранилищам данных разных уровней.
Статические свойства класса Store:
- Data — возвращает экземпляр провайдера хранилища данных.
- Cache — возвращает экземпляр провайдера кэша.
Получить доступ к хранилищам данных и кэша
Способы получения доступа к хранилищам данных и кэша:
- Через пользовательское подключение UserConnection.
- Через прокси-классы.
Получить доступ к хранилищам данных и кэша через UserConnection
Получить доступ к хранилищам данных и кэша приложения из исходного кода позволяют свойства статического класса Store. Альтернативным способом доступа к хранилищу данных и кэшу является доступ через экземпляр класса UserConnection. Этот способ позволяет избежать использования длинных имен свойств и подключения дополнительных сборок. Для обеспечения миграции от фреймворка .NET Framework к .NET Core необходимо заменить статические свойства на подключение через UserConnection.
Вспомогательные свойства класса UserConnection, которые позволяют получить быстрый доступ к хранилищам данных и кэшу разных уровней:
- ApplicationCache — возвращает ссылку на кэш уровня Application.
- WorkspaceCache — возвращает ссылку на кэш уровня Workspace.
- SessionCache — возвращает ссылку на кэш уровня Session.
- RequestData — возвращает ссылку на хранилище данных уровня Request.
- SessionData — возвращает ссылку на хранилище данных уровня Session.
- ApplicationData — возвращает ссылку на хранилище данных уровня Application.
Пример работы с кэшем через класс UserConnection приведен ниже.
Получить доступ к хранилищам данных и кэша через прокси-классы
Прокси-классы — это промежуточное звено между хранилищами и кодом, который получает доступ к хранилищам. Назначение прокси-классов — выполнение промежуточных действий над данными перед их чтением из хранилища или записью в хранилище. Каждый прокси-класс является хранилищем.
Действия, которые позволяют выполнять прокси-классов:
- Выполнить первоначальную настройку и конфигурирование приложения.
- Разграничить данные пользователей приложения.
- Выполнить другие промежуточные действия с данными перед их добавлением в хранилище.
Чтобы настроить использование прокси-классов для хранилищ данных и кэшей:
- Добавьте секцию proxies в секции storeDataAdapters и storeCacheAdapters конфигурационного файла Web.config, который находится в корневом каталоге приложения.
- В секции proxies перечислите все прокси-классы хранилища.
При загрузке приложения настройки считываются из конфигурационного файла и применяются к соответствующему виду хранилища. Таким образом можно выстраивать цепочки прокси-классов с последовательным вызовом. Порядок вызова прокси-классов цепочки соответствует порядку в конфигурационном файле. Первым из цепочки вызывается прокси-класс, который указан последним в секции proxies.
Особенности настройки цепочки прокси-классов:
- Конечной точкой применения цепочки прокси-классов является кэш или хранилище данных, для которого эта цепочка определяется.
- Каждый прокси-класс работает или с хранилищем данных, или с хранилищем кэша. Вид хранилища определяется с помощью свойств ICacheStoreProxy.CacheStore или IDataStoreProxy.DataStore. Свойство может ссылаться на другой прокси-класс, на конечное хранилище или кэш, но это неизвестно для прокси-класса. Прокси-класс может выступать в качестве хранилища, с которым работают другие прокси-классы.
Пример настройки прокси-классов приведен ниже.
Цепочка вызова прокси-классов хранилища данных RequestDataProxyName3 —> RequestDataProxyName2 —> RequestDataProxyName1 —> RequestDataAdapterClassName (конечное хранилище данных уровня запроса).
Прокси-классы позволяют разделить данные между пользователями. Наиболее простым решением этой задачи является трансформация ключей значений перед их добавлением в хранилище (например, путем добавления к ключу дополнительного префикса пользователя). Использование таких прокси-классов обеспечивает уникальность ключей хранилища. Это позволяет избежать потери и искажения данных при одновременной записи значений с одинаковым ключом разными пользователями.
Прокси-классы позволяют реализовывать логику выполнения любых произвольных действий с данными перед их добавлением в хранилище или получением из хранилища. Реализация логики обработки данных в прокси-классе позволяет избежать дублирования кода, что облегчает его модификацию и сопровождение.
Базовые интерфейсы прокси-классов
- Terrasoft.Core.Store.IDataStoreProxy — интерфейс прокси-классов хранилища данных.
- Terrasoft.Core.Store.ICacheStoreProxy — интерфейс прокси-классов кэша.
Чтобы использовать класс в качестве прокси-класса для работы с хранилищами, реализуйте один или оба интерфейса.
Каждый из этих интерфейсов имеет одно свойство — ссылку на хранилище или кэш, с которым работает текущий прокси-класс. Для интерфейса IDataStoreProxy это свойство DataStore, а для интерфейса ICacheStoreProxy — свойство CacheStore.
Прокси-классы трансформации ключей
Прокси-классы, которые реализуют логику трансформации ключей значений хранилища:
- Terrasoft.Core.Store.KeyTransformerProxy — базовый абстрактный класс всех прокси-классов, которые трансформируют ключи кэша. Реализует методы и свойства интерфейса ICacheStoreProxy. Чтобы избежать дублирования логики, при создании пользовательских прокси-классов в качестве родительского используйте класс KeyTransformerProxy.
-
Класс Terrasoft.Core.Store.PrefixKeyTransformerProxy — прокси-класс, который трансформирует ключи кэша путем добавления к ним заданного префикса.
Пример работы с кэшем уровня сессии через прокси-класс PrefixKeyTransformerProxy приведен ниже.
Пример работы с кэшем уровня сессии через прокси-класс PrefixKeyTransformerProxyВ результате переменные valueFromProxyCache и valueFromGlobalCache содержат одинаковое значение CachedValue.
-
Класс Terrasoft.Core.Store.DataStoreKeyTransformerProxy — прокси-класс, который трансформирует ключи хранилища данных путем добавления к ним заданного префикса.
Пример работы с хранилищем данных через прокси-класс DataStoreKeyTransformerProxy приведен ниже.
Пример работы с хранилищем данных через прокси-класс DataStoreKeyTransformerProxyВ результате переменные valueFromProxyStorage и valueFromGlobalStorage бсодержат одинаковое значение StoredValue.
Локальное кэширование данных
На базе прокси-классов в Creatio реализован механизм локального кэширования данных. Назначение кэширования данных — снижение нагрузки на сервер хранения данных и времени выполнения запросов при работе с редко изменяемыми данными.
Логику механизма локального кэширования реализует внутренний прокси-класс LocalCachingProxy, который выполняет кэширование данных на текущем узле веб-фермы. Класс проверяет время жизни кэшированных объектов и получает данные из глобального кэша, если кэшированные данные не актуальны.
Методы расширения интерфейса ICacheStore статического класса CacheStoreUtilities, которые используются для локального кэширования:
- WithLocalCaching() — переопределенный метод, который возвращает экземпляр класса LocalCachingProxy.
- WithLocalCachingOnly(string) — выполняет локальное кэширование данных заданной группы элементов с проверкой их актуальности.
- ExpireGroup(string) — устанавливает признак устаревания для заданной группы элементов. При вызове этого метода все элементы заданной группы становятся неактуальными и не возвращаются при запросе данных.
Пример работы с кэшем рабочего пространства с использованием локального кэширования приведен ниже.
Особенности использования хранилищ данных и кэша
Особенности, которые необходимо учитывать для повышения эффективности работы с хранилищами данных и кэша:
- В хранилища добавляются только сериализуемые объекты. Это обусловлено спецификой работы с хранилищами ядра приложения. При сохранении данных в хранилища (за исключением хранилища данных уровня Request) объект предварительно сериализуется, а при получении — десериализуется.
-
Обращение к хранилищу является ресурсоемкой операцией, поэтому необходимо избегать лишних обращений к хранилищу в коде.
Примеры работы с хранилищами приведены ниже.
-
Любые изменения состояния объекта, который считан из хранилища данных или кэша, выполняются в памяти локально и автоматически не фиксируются в хранилище. Чтобы изменения отобразились в хранилище, явно запишите в хранилище измененный объект.
Пример записи данных в хранилище приведен ниже.
Пример записи данных в хранилище