Introduce a MessageGroup.condition (#3517)

* Introduce a `groupConditionSupplier` for MGS

* Add a `MessageGroup.condition` option
* Add a `MessageGroupStore.conditionSupplier` option
* Use it from the `SimpleMessageStore.addMessagesToGroup()` API
to populate `condition` (if any) into a `MessageGroup`
* Introduce a `GroupConditionProvider` contract to be implemented
on those `ReleaseStrategy` contracts which could be aware of group condition
* Populated a `GroupConditionProvider.getGroupConditionSupplier()`
into a `MessageGroupStore` from the `AbstractCorrelatingMessageHandler`
for end-user convenience
* Rework a `FileMarkerReleaseStrategy` to implement a `GroupConditionProvider`
to provide a function which produces a condition from `file_lineCount` header
of the `END` marker message
* Make the `FileMarkerReleaseStrategy` logic already based on the condition from a group
* Delegate `GroupConditionProvider` from the `FileAggregator`
* Add test for empty file aggregation

* * Implement `condition` in the `AbstractKeyValueMessageStore` and `MongoDbMessageStore`
* Test `condition` for `mongo-aggregator-config.xml` and `FileAggregatorTests` against GemFire

* * Implement `condition` in the `ConfigurableMongoDbMessageStore`

* * Implement `condition` in the `JdbcMessageStore`
* `FileAggregatorTests` against `JdbcMessageStore`
* Refactor `JdbcMessageStore` for better handling of message group metadata
* Remove unused `MARKED` column in the DDL in favor of newly introduced `CONDITION`

* * Add docs for message group condition

* * Move `conditionSupplier` option from MGS to AbstractCorrelatingMH
* Make it as a `BiFunction` to propagate existing condition alongside with the
message to consult
* Expose `groupConditionSupplier` in Java & XML DSLs

* * Fix language in docs
This commit is contained in:
Artem Bilan
2021-03-23 14:23:46 -04:00
committed by GitHub
parent 7ee3db9ca5
commit 7e9552974c
39 changed files with 533 additions and 151 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2021 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.
@@ -236,6 +236,11 @@ public abstract class AbstractConfigurableMongoDbMessageStore extends AbstractMe
throw NOT_IMPLEMENTED;
}
@Override
public void setGroupCondition(Object groupId, String condition) {
throw NOT_IMPLEMENTED;
}
@Override
public void setLastReleasedSequenceNumberForGroup(Object groupId, int sequenceNumber) {
throw NOT_IMPLEMENTED;

View File

@@ -131,8 +131,8 @@ public class ConfigurableMongoDbMessageStore extends AbstractConfigurableMongoDb
.create(this, groupId, createdTime, complete);
messageGroup.setLastModified(lastModifiedTime);
messageGroup.setLastReleasedMessageSequenceNumber(lastReleasedSequence);
messageGroup.setCondition(messageDocument.getCondition());
return messageGroup;
}
else {
return new SimpleMessageGroup(groupId);
@@ -157,10 +157,13 @@ public class ConfigurableMongoDbMessageStore extends AbstractConfigurableMongoDb
int lastReleasedSequence = 0;
boolean complete = false;
String condition = null;
if (messageDocument != null) {
createdTime = messageDocument.getGroupCreatedTime();
lastReleasedSequence = messageDocument.getLastReleasedSequence();
complete = messageDocument.isComplete();
condition = messageDocument.getCondition();
}
for (Message<?> message : messages) {
@@ -171,7 +174,9 @@ public class ConfigurableMongoDbMessageStore extends AbstractConfigurableMongoDb
document.setGroupCreatedTime(createdTime);
document.setLastModifiedTime(messageDocument == null ? createdTime : System.currentTimeMillis());
document.setSequence(getNextId());
if (condition != null) {
document.setCondition(condition);
}
addMessageDocument(document);
}
}
@@ -221,6 +226,11 @@ public class ConfigurableMongoDbMessageStore extends AbstractConfigurableMongoDb
updateGroup(groupId, lastModifiedUpdate().set(MessageDocumentFields.LAST_RELEASED_SEQUENCE, sequenceNumber));
}
@Override
public void setGroupCondition(Object groupId, String condition) {
updateGroup(groupId, lastModifiedUpdate().set("condition", condition));
}
@Override
public void completeGroup(Object groupId) {
updateGroup(groupId, lastModifiedUpdate().set(MessageDocumentFields.COMPLETE, true));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2014-2021 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.
@@ -22,6 +22,7 @@ import org.springframework.data.annotation.AccessType;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.util.Assert;
@@ -61,6 +62,8 @@ public class MessageDocument {
private Integer lastReleasedSequence = 0;
private String condition;
private long sequence;
public MessageDocument(Message<?> message) {
@@ -151,6 +154,15 @@ public class MessageDocument {
return this.groupId;
}
@Nullable
public String getCondition() {
return this.condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
public long getSequence() {
return this.sequence;
}

View File

@@ -286,6 +286,7 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
.create(this, groupId, createdTime, complete);
messageGroup.setLastModified(lastModifiedTime);
messageGroup.setLastReleasedMessageSequenceNumber(lastReleasedSequence);
messageGroup.setCondition(messageWrapper.get_Condition());
return messageGroup;
}
@@ -304,11 +305,12 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
long createdTime = System.currentTimeMillis();
int lastReleasedSequence = 0;
boolean complete = false;
String condition = null;
if (messageDocument != null) {
createdTime = messageDocument.get_Group_timestamp();
lastReleasedSequence = messageDocument.get_LastReleasedSequenceNumber();
complete = messageDocument.get_Group_complete();
condition = messageDocument.get_Condition();
}
for (Message<?> message : messages) {
@@ -318,7 +320,10 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
wrapper.set_Group_update_timestamp(messageDocument == null ? createdTime : System.currentTimeMillis());
wrapper.set_Group_complete(complete);
wrapper.set_LastReleasedSequenceNumber(lastReleasedSequence);
wrapper.set_Sequence(getNextId());
wrapper.setSequence(getNextId());
if (condition != null) {
wrapper.set_Condition(condition);
}
addMessageDocument(wrapper);
}
@@ -393,9 +398,14 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
return (int) lCount;
}
@Override
public void setGroupCondition(Object groupId, String condition) {
updateGroup(groupId, lastModifiedUpdate().set("_condition", condition));
}
@Override
public void setLastReleasedSequenceNumberForGroup(Object groupId, int sequenceNumber) {
this.updateGroup(groupId, lastModifiedUpdate().set(LAST_RELEASED_SEQUENCE_NUMBER, sequenceNumber));
updateGroup(groupId, lastModifiedUpdate().set(LAST_RELEASED_SEQUENCE_NUMBER, sequenceNumber));
}
@Override
@@ -618,6 +628,7 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
if (completeGroup != null) {
wrapper.set_Group_complete(completeGroup);
}
wrapper.set_Condition((String) sourceMap.get("_condition"));
return (S) wrapper;
}
@@ -860,6 +871,8 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
private volatile boolean _group_complete; // NOSONAR name
private volatile String _condition; // NOSONAR name
@SuppressWarnings(UNUSED)
private long sequence;
@@ -930,7 +943,15 @@ public class MongoDbMessageStore extends AbstractMessageGroupStore
this._group_complete = completedGroup;
}
public void set_Sequence(long sequence) { // NOSONAR name
public String get_Condition() {
return this._condition;
}
public void set_Condition(String condition) {
this._condition = condition;
}
public void setSequence(long sequence) {
this.sequence = sequence;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@@ -24,6 +24,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.UUID;
import java.util.function.BiFunction;
import org.junit.After;
import org.junit.Before;
@@ -31,6 +32,7 @@ import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.integration.aggregator.ReleaseStrategy;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.history.MessageHistory;
@@ -54,6 +56,11 @@ import org.springframework.messaging.support.GenericMessage;
*/
public abstract class AbstractMongoDbMessageGroupStoreTests extends MongoDbAvailableTests {
public static final BiFunction<Message<?>, String, String> CONDITION_SUPPLIER = (m, c) -> "10";
public static final ReleaseStrategy RELEASE_STRATEGY =
group -> group.size() == Integer.parseInt(group.getCondition());
protected final GenericApplicationContext testApplicationContext = TestUtils.createTestApplicationContext();
@Before

View File

@@ -3,12 +3,21 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration https://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo.xsd">
http://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<int:aggregator input-channel="inputChannel" output-channel="outputChannel" message-store="mongoStore"
release-strategy-expression="size() == 10"/>
release-strategy="releaseStrategy"
group-condition-supplier="conditionSupplier"/>
<util:constant id="releaseStrategy"
static-field="org.springframework.integration.mongodb.store.MongoDbMessageGroupStoreTests.RELEASE_STRATEGY"/>
<util:constant id="conditionSupplier"
static-field="org.springframework.integration.mongodb.store.MongoDbMessageGroupStoreTests.CONDITION_SUPPLIER"/>
<mongo:auditing/>
@@ -20,4 +29,4 @@
<constructor-arg value="#{T (org.springframework.integration.mongodb.store.MongoDbMessageGroupStoreTests).MONGO_DATABASE_FACTORY}"/>
</bean>
</beans>
</beans>

View File

@@ -3,12 +3,21 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration https://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo.xsd">
http://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<int:aggregator input-channel="inputChannel" output-channel="outputChannel" message-store="mongoStore"
release-strategy-expression="size() == 10"/>
release-strategy="releaseStrategy"
group-condition-supplier="conditionSupplier"/>
<util:constant id="releaseStrategy"
static-field="org.springframework.integration.mongodb.store.MongoDbMessageGroupStoreTests.RELEASE_STRATEGY"/>
<util:constant id="conditionSupplier"
static-field="org.springframework.integration.mongodb.store.MongoDbMessageGroupStoreTests.CONDITION_SUPPLIER"/>
<mongo:auditing/>