Общий принцип
Контроль транзакций осуществляется на уровне релизации сценария / маршрута ИР.
Реализация сценария / маршрута для обработки каждого объекта (сигнал, сообщение, передача в систему получателя и прочее) создает отдельную траназкцию, для обеспечания непрерывной обработки всех операций движения сообщения по маршруту в случае возникновения исключительных ситуаций обработки конткретного объекта на любом из этапов передачи.
Техническая спецификация
Транзакционность выборок / получения коллекций обеспечивается использованием CollectionService
Передача управления транзакциями
Для передачи управления транзакциями на уровень управления реализации ИР, платформенная задача объявляется с нотацией taskTransactionalManagement = true
@ScheduleTask(name = "CorpRouteInputOutput", taskTransactionalManagement = true,minute = "*/1", active = true, timeout = 10, allNodes = true, type= SheduleType.Singleton) public class CorpRouteInputOutput implements ScheduleTaskHandle {
Варианты реализации
Вызов транзакционного когда с помощью TransactionalContext
В СМ-И реализован интерфейс TransactionalContext реализующий вызов кода в транзакционной обертки
public class CorpRouteInputOutput implements ScheduleTaskHandle { @Autowired TransactionalContext transactionalContext; @Override public String execute(EJBContext ejbContext, SessionContext sessionContext, ScheduleTaskParameters parameters) throws InterruptedException { transactionalContext.executeInTransaction(()-> { // обработка }); return null; } }
public class CorpRouteInputOutput implements ScheduleTaskHandle { @Autowired TransactionalContext transactionalContext; @Override public String execute(EJBContext ejbContext, SessionContext sessionContext, ScheduleTaskParameters parameters) throws InterruptedException { TransactionalContext.TransactionResult<String> example = transactionalContext.executeInTransaction(()->{ return "1"; }); System.out.println(example.executionResult()); return null; } }
Автоматическое управление
Подключение транзакционности с использованием с Spring аннотации @Transactional
@Transactional(propagation = Propagation.REQUIRES_NEW) public boolean processSignal() { boolean result = false; // обработка объекта return result; }
Программное управление
Реализация этапа обработки
Для каждого этапа обработки объекта необходимо создать отдельную функцию, реализация которой полностью обернута в секцию try..catch
Внутри try..catch обработка объекта начинается с начала транзакции SessionContext.getUserTransaction().begin() и после всех операций завершается транзакция SessionContext.getUserTransaction().commit().
В области обработки исключения, выполняется откат транзации вызовом SessionContext.getUserTransaction().rollback() с проверкой открытости транзакции SessionContext.getUserTransaction().getStatus() == Status.STATUS_ACTIVE или Status.STATUS_MARKED_ROLLBACK
Важно
Выход rollback необходимо оборачивать в try catch
private boolean processSignal(SessionContext sessionContext) { boolean result = false; try { sessionContext.getUserTransaction().begin(); // обработка объекта sessionContext.getUserTransaction().commit(); } catch (Exception ex) { // логирование ошибки try { if (sessionContext.getUserTransaction().getStatus() == sessionContext.STATUS_ACTIVE || sessionContext.getUserTransaction().getStatus() == sessionContext.STATUS_MARKED_ROLLBACK) { sessionContext.getUserTransaction().rollback(); } } catch (Exception ignoreEx) { } } return result; }
Реализация маршрута
Так как обработка каждого объекта является отдельной транзакцией, то при выполении интеграционного маршрута необходимо обрабтывать взведения флага отмены задания, получаемый методом: SessionContext.wasCancelCalled()
Проверка отмены выполнения задания необходимо выполнять перед началом транзакции, то есть перед обработкой каждого объекта и в случае устанволенного флага завершать выполнение без формирования ошибок.
public boolean executeRoute(SessionContext sessionContext) { boolean result = true; // получение коллекции объектов для обработки for (Signal signal : signalCollection) { if (!sessionContext.wasCancelCalled()) { processSignal(signal, sessionContext); } else { return true; } } // получение коллекции объектов для сообщений for (Message message : message Collection) { if (!sessionContext.wasCancelCalled()) { processMessage(message , sessionContext); } else { return true; } } return result; }