GH-5123: Add LockRegistry to AbstractMessageGroupStore

Fixes: https://github.com/spring-projects/spring-integration/issues/5123

When `RedisMessageStore`, for example, adds and removes messages, it operates on two keys separately, which may cause problems in multi-threading due to non-atomic operations.
Although using Redis to delay messages is not a good idea, the abnormal loss of messages in the logs alerted me when the number of requests was not large.
By comparing the logs, the problem that the message group representing the metadata is not consistent with the actual message.

A simple solution is to add lock like in the `SimpleMessageStore`, which is also the approach taken in this pull request.

* Add `LockRegistry` to `AbstractMessageGroupStore`
* Normalize access levels and method name about the lock of `MessageGroupStore`
* Add document about the lock of `AbstractMessageGroupStore`
This commit is contained in:
NaccOll
2024-11-23 13:58:23 -05:00
committed by Artem Bilan
parent 12a643d494
commit 9962ee49a2
14 changed files with 284 additions and 214 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -80,6 +80,7 @@ import org.springframework.util.StringUtils;
* @author Gary Russell
* @author Artem Bilan
* @author Ngoc Nhan
* @author Youbin Wu
*
* @since 2.0
*/
@@ -472,7 +473,7 @@ public class JdbcMessageStore extends AbstractMessageGroupStore
}
@Override
public void addMessagesToGroup(Object groupId, Message<?>... messages) {
protected void doAddMessagesToGroup(Object groupId, Message<?>... messages) {
String groupKey = getKey(groupId);
MessageGroupMetadata groupMetadata = getGroupMetadata(groupKey);
@@ -576,7 +577,7 @@ public class JdbcMessageStore extends AbstractMessageGroupStore
}
@Override
public void removeMessagesFromGroup(Object groupId, Collection<Message<?>> messages) {
protected void doRemoveMessagesFromGroup(Object groupId, Collection<Message<?>> messages) {
Assert.notNull(groupId, "'groupId' must not be null");
Assert.notNull(messages, "'messages' must not be null");
@@ -621,7 +622,7 @@ public class JdbcMessageStore extends AbstractMessageGroupStore
}
@Override
public boolean removeMessageFromGroupById(Object groupId, UUID messageId) {
protected boolean doRemoveMessageFromGroupById(Object groupId, UUID messageId) {
String groupKey = getKey(groupId);
String messageKey = getKey(messageId);
int messageToGroupRemoved =
@@ -634,7 +635,7 @@ public class JdbcMessageStore extends AbstractMessageGroupStore
}
@Override
public void removeMessageGroup(Object groupId) {
protected void doRemoveMessageGroup(Object groupId) {
String groupKey = getKey(groupId);
this.jdbcTemplate.update(getQuery(Query.DELETE_MESSAGES_FROM_GROUP),
@@ -653,7 +654,7 @@ public class JdbcMessageStore extends AbstractMessageGroupStore
}
@Override
public void completeGroup(Object groupId) {
protected void doCompleteGroup(Object groupId) {
final String groupKey = getKey(groupId);
if (logger.isDebugEnabled()) {
@@ -664,7 +665,7 @@ public class JdbcMessageStore extends AbstractMessageGroupStore
}
@Override
public void setGroupCondition(Object groupId, String condition) {
protected void doSetGroupCondition(Object groupId, String condition) {
Assert.notNull(groupId, "'groupId' must not be null");
String groupKey = getKey(groupId);
Timestamp updatedDate = new Timestamp(System.currentTimeMillis());
@@ -675,7 +676,7 @@ public class JdbcMessageStore extends AbstractMessageGroupStore
}
@Override
public void setLastReleasedSequenceNumberForGroup(Object groupId, int sequenceNumber) {
protected void doSetLastReleasedSequenceNumberForGroup(Object groupId, int sequenceNumber) {
Assert.notNull(groupId, "'groupId' must not be null");
String groupKey = getKey(groupId);
@@ -687,7 +688,7 @@ public class JdbcMessageStore extends AbstractMessageGroupStore
}
@Override
public Message<?> pollMessageFromGroup(Object groupId) {
protected Message<?> doPollMessageFromGroup(Object groupId) {
String key = getKey(groupId);
Message<?> polledMessage = doPollForMessage(key);