Контекст вызова
1. Создание и жизненный цикл контекста вызова
Для того, чтобы можно было реализовать требования распределения прав доступа и логирования действий, любая операция над данными в Celesta производится от имени некоторого пользователя, «анонимных» операций быть не может.
Поэтому любой Celesta-код выполняется в некотором контексте вызова, определяемом экземпляром класса (CallContext
).
Контекст вызова содержит в себе имя пользователя, а привязка имени пользователя к роли определяет разрешения на доступ к таблицам, а также обеспечивает возможность логирования изменений, производимых от его имени.
Создание контекста вызова производится на уровне контроллера, где предполагается известным (по переданному в запрос токену, цифровой подписи или каким-либо ещё способом) имя пользователя, выполняющего операции.
Контекст создаётся с помощью конструктора
CallContext(String userId)
При отсутствии необходимости как-либо учитывать имя пользователя, а также использовать распределение прав доступа
к таблицам, можно воспользоваться субклассом SystemCallContext
,
конструктор которого не принимает параметров.
В этом случае создаётся контекст «системного пользователя», имеющего полные
права доступа ко всем таблицам.
Любой созданный таким образом контекст далее проходит следующий жизненный цикл:
-
Активация. Вызов метода
activate(..)
, в который передаётся ссылка на объектCelesta
и имя выполняемой процедуры. В этот момент открывается неявная транзакция в базе данных и начинается отсчёт времени выполнения вызова. -
Вызов сервисного метода. Контекст передаётся в качестве параметра в сервисный метод и используется для создания курсоров.
-
Закрытие. Вызов метода
close()
, фиксирующего транзакцию и закрывающего все незакрытые курсоры с высвобождением всех ресурсов JDBC.
Разработчику обычно не требуется выполнять активацию и закрытие контекста самостоятельно, т. к. они выполняются автоматически фреймворком Celesta.
-
При использовании Celesta Spring Boot starter активация и закрытие курсора выполняются при вызове методов сервисов, помеченных аннотацией
@CelestaTransaction
. Таким образом на этапе разработки достаточно передавать в них неактивированный контекст. Прокси-объект, создаваемый фреймворком Spring вокруг экземпляра сервисного класса, будет выполнять активацию, закрытие контекста и откат транзакции базы данных в случае необработанного исключения. -
При использовании CelestaUnit в параметры тестов, имеющих тип
CallContext
, будет передан уже активированный системный контекст на базе Celesta, запущенной с базой данных H2 в in-memory режиме. Закрытие контекста, а также фиксация/откат изменений также обеспечиваются в CelestaUnit прозрачно для разработчика.
2. Использование контекста вызова
Каждый из методов сервисного слоя, использующих Celesta, принимает в качестве аргумента объект ru.curs.celesta.CallContext
.
Этот объект предназначен, в первую очередь, чтобы быть аргументом конструкторов курсоров.
Однако и сам по себе контекст вызова имеет публично доступные методы и свойства, которые могут быть использованы внутри сервисного метода:
- commit()
-
фиксирует текущую транзакцию. Вызывать данный метод требуется только в редких случаях, когда транзакцию обработки данных необходимо разбить на несколько частей. Обычно в вызове этого метода необходимости нет, т. к. транзакция фиксируется автоматически по завершении процедуры.
- rollback()
-
откатывает текущую транзакцию.
- getCelesta()
-
вызывает текущий экземпляр объекта Celesta. Необходимо, например, для получения информации о метаданных.
- getUserId()
-
возвращает имя пользователя, от лица которого производятся действия.
- getStartTime()
-
возвращает время создания контекста вызова (время начала работы Celesta-процедуры, полученное с помощью
System.currentTimeMillis()
). - getDurationNs()
-
возвращает время жизни контекста вызова в наносекундах, измеренное как разница между значениями, возвращаемыми вызовами
System.nanoTime()
. - getProcName()
-
возвращает имя процедуры, которая была изначально вызвана из контроллера (используется для нужд отладки).
- getDBPid()
-
возвращает PID (process identifier) текущего соединения с базой данных (используется для нужд отладки).