Подмножество изменений в транзакции иногда незаметно вскоре после принятия - PullRequest
0 голосов
/ 11 февраля 2019

Рассмотрим следующий контекст:

2 пружинных канала интеграции, каждый из которых находится в отдельных транзакциях базы данных.В конце первой транзакции сообщение помещается во второй канал.В первом канале элементы создаются в базе данных, которая позднее используется соответствующим сообщением, которое было отправлено из первого канала во второй канал.

Чтобы убедиться, что транзакция из канала 1 полностью зафиксированадо запуска второго канала наш подкласс JpaTransactionManager регистрирует TransactionSynchronization в методе prepareForCommit, который он переопределяет из JpaTransactionManager

Поток (канал 1) выглядит следующим образом:

  • Выполнить всю обработку сообщений и обработку базы данных
  • Последний шаг потока регистрирует TransactionSynchronization, который выполняет MessageChannel.send в фазе afterCommit для отправки сообщения на канал 2

Насколько я понимаю, во время отправки сообщения на второй канал (в afterCommit) все изменения, которые были сделаны в транзакции базы данных канала 1, сбрасываются и фиксируются.

Теперь второй канал выполняет некоторую работу (например, MQ PUT) и позже обновляет запись, созданную в первом потоке.Теперь мы заметили, что метод репозитория не возвратил записи в базе данных, но он будет виден в таблице позже.Другие записи, которые также были созданы в транзакции первого канала, однако, являются видимыми.Это происходит только один раз каждые несколько тысяч сообщений, обычно они есть, но иногда они не видны для второго канала через несколько миллисекунд после совершения транзакции каналом 1.

Я создал изображение, которое должно иллюстрироватьit: enter image description here

Chain 1 - это первая цепочка, состоящая из нескольких ServiceActivators, которые выполняют работу с базой данных, сплиттер, который генерирует больше сообщений, а затем еще один ServiceActivator, которыйЯ назвал SENDER, который регистрирует TransactionSynchronization, который (насколько я понимаю) должен отправлять, например, 3 сгенерированных сообщения в цепочку 2 после полной фиксации красной транзакции и, следовательно, до начала голубой транзакции.

OneЯ заметил, что записи, которые иногда присутствовали, а иногда и не все, в одном методе, который (не специально) использует javax.transaction.Transactional вместо org.springframework.transaction.annotation.Transactional.Тем не менее, мы используем пружинное ядро ​​5.0.8.RELEASE , и в других вопросах я видел, что это должно иметь значение 0 с весны 4.2.x.

1 Ответ

0 голосов
/ 11 февраля 2019

Я не думаю, что afterCommit - это правильное место для отправки сообщений в нисходящем направлении.

Этого должно быть достаточно, чтобы иметь активатор службы для метода POJO, помеченный @Transactional.Таким образом, транзакция будет начинаться и заканчиваться в точности вокруг этого вызова метода.Результат метода будет отправлен на выходной канал уже после того, как эта транзакция будет зафиксирована.

ОБНОВЛЕНИЕ

Лучший способ выполнить ваши требования -<gateway> вокруг вашей Цепи1.Таким образом, TX будет зафиксирован там перед созданием ответа на Chain2 из шлюза.

С TransactionSynchronization::afterCommit нет никакой гарантии, что TX будет зафиксирован в БД, когда QueueChannel готов копросы сообщений.Хотя вы можете использовать JdbcChannelMessageStore для транзакционного хранения сообщений.Таким образом, они не будут видны до тех пор, пока не передадут TX в БД.

Подробнее о <gateway> в Документах: https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-routing-chapter.html#_calling_a_chain_from_within_a_chain

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...