Skip to content

Commit

Permalink
#550 added QueueSplitterConfigurationParser
Browse files Browse the repository at this point in the history
  • Loading branch information
zorba71 committed Jan 22, 2024
1 parent 6978e34 commit dffde37
Show file tree
Hide file tree
Showing 8 changed files with 390 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package org.swisspush.gateleen.queue.queuing.splitter;

import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;

/**
* Container holding configuration values for {@link QueueSplitterHandler} identified
* by a queue pattern.
*
* @author https://github.com/gcastaldi [Giannandrea Castaldi]
*/
public class QueueSplitterConfiguration {

private final Pattern queue;

private final String postfixDelimiter;

@Nullable
private final List<String> postfixFromStatic;

@Nullable
private final String postfixFromHeader;

@Nullable
private final String postfixFromUrl;


public QueueSplitterConfiguration(
Pattern queue,
String postfixDelimiter,
@Nullable List<String> postfixFromStatic,
@Nullable String postfixFromHeader,
@Nullable String postfixFromUrl) {
this.queue = queue;
this.postfixDelimiter = postfixDelimiter;
this.postfixFromStatic = postfixFromStatic;
this.postfixFromHeader = postfixFromHeader;
this.postfixFromUrl = postfixFromUrl;
}

public Pattern getQueue() {
return queue;
}

public String getPostfixDelimiter() {
return postfixDelimiter;
}

@Nullable
public List<String> getPostfixFromStatic() {
return postfixFromStatic;
}

@Nullable
public String getPostfixFromHeader() {
return postfixFromHeader;
}

@Nullable
public String getPostfixFromUrl() {
return postfixFromUrl;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
QueueSplitterConfiguration that = (QueueSplitterConfiguration) o;
return Objects.equals(queue, that.queue) &&
Objects.equals(postfixDelimiter, that.postfixDelimiter) &&
Objects.equals(postfixFromStatic, that.postfixFromStatic) &&
Objects.equals(postfixFromHeader, that.postfixFromHeader) &&
Objects.equals(postfixFromUrl, that.postfixFromUrl);
}

@Override
public int hashCode() {
return Objects.hash(queue, postfixDelimiter, postfixFromStatic, postfixFromHeader, postfixFromUrl);
}

@Override
public String toString() {
return "QueueSplitterConfiguration{" +
"queue=" + queue +
", postfixDelimiter='" + postfixDelimiter + '\'' +
", postfixFromStatic=" + postfixFromStatic +
", postfixFromHeader='" + postfixFromHeader + '\'' +
", postfixFromUrl='" + postfixFromUrl + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package org.swisspush.gateleen.queue.queuing.splitter;

import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.swisspush.gateleen.core.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
* Parses the splitter configuration resource in to a list of {@link QueueSplitterConfiguration}
*
* @author https://github.com/gcastaldi [Giannandrea Castaldi]
*/
public class QueueSplitterConfigurationParser {

private static final Logger log = LoggerFactory.getLogger(QueueSplitterConfigurationParser.class);
public static final String POSTFIX_FROM_STATIC_KEY = "postfixFromStatic";
public static final String POSTFIX_FROM_HEADER_KEY = "postfixFromHeader";
public static final String POSTFIX_FROM_URL_KEY = "postfixFromUrl";
public static final String POSTFIX_DELIMITER_KEY = "postfixDelimiter";
public static final String DEFAULT_POSTFIX_DELIMITER = "-";

static List<QueueSplitterConfiguration> parse(Buffer configurationResourceBuffer, Map<String, Object> properties) {

JsonObject config;
List<QueueSplitterConfiguration> queueSplitterConfigurations = new ArrayList<>();
try {
String resolvedConfiguration = StringUtils.replaceWildcardConfigs(
configurationResourceBuffer.toString(StandardCharsets.UTF_8),
properties
);
config = new JsonObject(Buffer.buffer(resolvedConfiguration));
} catch (Exception ex) {
log.warn("Could not replace wildcards with environment properties for queue splitter configurations or json invalid. Here the reason: {}",
ex.getMessage());
return queueSplitterConfigurations;
}

for (String queuePattern : config.fieldNames()) {
Pattern pattern = Pattern.compile(queuePattern);
JsonObject queueConfig = config.getJsonObject(queuePattern);
JsonArray postfixFromStatic = queueConfig.getJsonArray(POSTFIX_FROM_STATIC_KEY);
if (postfixFromStatic != null) {
List<String> staticPostfixes = postfixFromStatic.stream().map(Object::toString).collect(Collectors.toList());
queueSplitterConfigurations.add(new QueueSplitterConfiguration(
pattern,
queueConfig.getString("postfixDelimiter", DEFAULT_POSTFIX_DELIMITER),
staticPostfixes,
null,
null
));
continue;
}
String postfixFromHeader = queueConfig.getString(POSTFIX_FROM_HEADER_KEY);
String postfixFromUrl = queueConfig.getString(POSTFIX_FROM_URL_KEY);
if (postfixFromHeader != null || postfixFromUrl != null) {
queueSplitterConfigurations.add(new QueueSplitterConfiguration(
pattern,
queueConfig.getString(POSTFIX_DELIMITER_KEY, DEFAULT_POSTFIX_DELIMITER),
null,
postfixFromHeader,
postfixFromUrl
));
} else {
log.warn("Queue splitter configuration without a postfix definition");
}
}

return queueSplitterConfigurations;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.swisspush.gateleen.queue.queuing.splitter;

/**
* Handler class for queues configured to be split in sub-queues.
*
* @author https://github.com/gcastaldi [Giannandrea Castaldi]
*/
public class QueueSplitterHandler {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package org.swisspush.gateleen.queue.queuing.splitter;

import io.vertx.core.buffer.Buffer;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.swisspush.gateleen.core.util.ResourcesUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
* Tests for {@link QueueSplitterConfigurationParser} class
*
* @author https://github.com/gcastaldi [Giannandrea Castaldi]
*/
@RunWith(VertxUnitRunner.class)
public class QueueSplitterConfigurationParserTest {

private final String CONFIGURATION_VALID = ResourcesUtils.loadResource(
"testresource_queuesplitter_configuration_valid",
true
);

private final String CONFIGURATION_INVALID = ResourcesUtils.loadResource(
"testresource_queuesplitter_configuration_invalid",
true
);

private final String CONFIGURATION_INVALID_JSON = ResourcesUtils.loadResource(
"testresource_queuesplitter_configuration_invalid_json",
true
);

private final String CONFIGURATION_WITH_PROPS = ResourcesUtils.loadResource(
"testresource_queuesplitter_configuration_with_props",
true
);

@Test
public void parseWithAllValid(TestContext context) {

// Given
Buffer configurationResourceBuffer = Buffer.buffer(CONFIGURATION_VALID);
HashMap<String, Object> properties = new HashMap<>();

// When
List<QueueSplitterConfiguration> configurations = QueueSplitterConfigurationParser.parse(
configurationResourceBuffer,
properties
);

// Then
context.assertEquals(3, configurations.size());

// Note that the order of the parsed configurations matters!
QueueSplitterConfiguration config_1 = configurations.get(0);
context.assertEquals(Pattern.compile("my-queue-1").pattern(), config_1.getQueue().pattern());
context.assertEquals("-", config_1.getPostfixDelimiter());
context.assertEquals(List.of("A", "B", "C", "D"), config_1.getPostfixFromStatic());
context.assertNull(config_1.getPostfixFromHeader());
context.assertNull(config_1.getPostfixFromUrl());

QueueSplitterConfiguration config_2 = configurations.get(1);
context.assertEquals(Pattern.compile("my-queue-[0-9]+").pattern(), config_2.getQueue().pattern());
context.assertEquals("+", config_2.getPostfixDelimiter());
context.assertNull(config_2.getPostfixFromStatic());
context.assertEquals("{x-rp-deviceid}", config_2.getPostfixFromHeader());
context.assertNull(config_2.getPostfixFromUrl());

QueueSplitterConfiguration config_3 = configurations.get(2);
context.assertEquals(Pattern.compile("my-queue-[a-zA-Z]+").pattern(), config_3.getQueue().pattern());
context.assertEquals("_", config_3.getPostfixDelimiter());
context.assertNull(config_3.getPostfixFromStatic());
context.assertNull(config_3.getPostfixFromHeader());
context.assertEquals(".*/path1/(.*)/path3/path4/.*", config_3.getPostfixFromUrl());
}

@Test
public void parseWithOneValidOneNot(TestContext context) {

// Given
Buffer configurationResourceBuffer = Buffer.buffer(CONFIGURATION_INVALID);
HashMap<String, Object> properties = new HashMap<>();

// When
List<QueueSplitterConfiguration> configurations = QueueSplitterConfigurationParser.parse(
configurationResourceBuffer,
properties
);

// Then
context.assertEquals(1, configurations.size());

QueueSplitterConfiguration config_1 = configurations.get(0);
context.assertEquals(Pattern.compile("my-queue-1").pattern(), config_1.getQueue().pattern());
context.assertEquals("-", config_1.getPostfixDelimiter());
context.assertEquals(List.of("A", "B", "C", "D"), config_1.getPostfixFromStatic());
context.assertNull(config_1.getPostfixFromHeader());
context.assertNull(config_1.getPostfixFromUrl());
}
@Test
public void parseWithInvalidJson(TestContext context) {

// Given
Buffer configurationResourceBuffer = Buffer.buffer(CONFIGURATION_INVALID_JSON);
HashMap<String, Object> properties = new HashMap<>();

// When
List<QueueSplitterConfiguration> configurations = QueueSplitterConfigurationParser.parse(
configurationResourceBuffer,
properties
);

// Then
context.assertEquals(0, configurations.size());
}

@Test
public void parseWithValidAndProps(TestContext context) {

// Given
Buffer configurationResourceBuffer = Buffer.buffer(CONFIGURATION_WITH_PROPS);
Map<String, Object> properties = Map.of("queue.splitter.delimiter", "_");

// When
List<QueueSplitterConfiguration> configurations = QueueSplitterConfigurationParser.parse(
configurationResourceBuffer,
properties
);

// Then
context.assertEquals(1, configurations.size());

QueueSplitterConfiguration config_1 = configurations.get(0);
context.assertEquals(Pattern.compile("my-queue-[0-9]+").pattern(), config_1.getQueue().pattern());
context.assertEquals("_", config_1.getPostfixDelimiter());
context.assertNull(config_1.getPostfixFromStatic());
context.assertEquals("{x-rp-deviceid}", config_1.getPostfixFromHeader());
context.assertNull(config_1.getPostfixFromUrl());
}
@Test
public void parseWithValidAndMissingProps(TestContext context) {

// Given
Buffer configurationResourceBuffer = Buffer.buffer(CONFIGURATION_WITH_PROPS);
Map<String, Object> properties = new HashMap<>();

// When
List<QueueSplitterConfiguration> configurations = QueueSplitterConfigurationParser.parse(
configurationResourceBuffer,
properties
);

// Then
context.assertEquals(0, configurations.size());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"my-queue-1" : {
"postfixFromStatic": [
"A",
"B",
"C",
"D"
]
},
"my-queue-[0-9]+" : {
"postfixDelimiter": "+"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"my-queue-1" : {
"postfixFromStatic": [
"A"
"B"
"C"
"D"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"my-queue-1" : {
"postfixFromStatic": [
"A",
"B",
"C",
"D"
]
},
"my-queue-[0-9]+" : {
"postfixDelimiter": "+",
"postfixFromHeader": "{x-rp-deviceid}"
},
"my-queue-[a-zA-Z]+" : {
"postfixDelimiter": "_",
"postfixFromUrl": ".*/path1/(.*)/path3/path4/.*"
}
}
Loading

0 comments on commit dffde37

Please sign in to comment.