Skip to content

Commit

Permalink
Memoize pattern match in GetAliases (elastic#113571)
Browse files Browse the repository at this point in the history
Previously, when GetAliases was called with multiple indices that share
an alias, findAliases would recheck the alias against the supplied alias
patterns for each index that used it. This change memoizes the pattern
check to avoid that redundant work.

Closes elastic#102676
  • Loading branch information
bcully authored Sep 27, 2024
1 parent c498dae commit 31bea56
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,7 @@ public Map<String, List<DataStreamAlias>> findDataStreamAliases(final String[] a
*
* @param aliases The aliases to look for. Might contain include or exclude wildcards.
* @param possibleMatches The data streams or indices that the aliases must point to in order to be returned
* @param getter A function that is used to get the alises for a given data stream or index
* @param getter A function that is used to get the aliases for a given data stream or index
* @param setter A function that is used to keep track of the found aliases
*/
private void findAliasInfo(final String[] aliases, final String[] possibleMatches, AliasInfoGetter getter, AliasInfoSetter setter) {
Expand All @@ -881,24 +881,30 @@ private void findAliasInfo(final String[] aliases, final String[] possibleMatche

boolean matchAllAliases = patterns.length == 0;

// memoize pattern match against aliases to avoid repeatedly matching when multiple indices share an alias
HashMap<String, Boolean> seenAliases = new HashMap<>();
Predicate<String> matcher = alias -> seenAliases.computeIfAbsent(alias, key -> {
boolean matched = matchAllAliases;
for (int i = 0; i < patterns.length; i++) {
if (include[i]) {
if (matched == false) {
String pattern = patterns[i];
matched = ALL.equals(pattern) || Regex.simpleMatch(pattern, key);
}
} else if (matched) {
matched = Regex.simpleMatch(patterns[i], key) == false;
}
}

return matched;
});

for (String index : possibleMatches) {
List<AliasInfo> filteredValues = new ArrayList<>();

List<? extends AliasInfo> entities = getter.get(index);
for (AliasInfo aliasInfo : entities) {
boolean matched = matchAllAliases;
String alias = aliasInfo.getAlias();
for (int i = 0; i < patterns.length; i++) {
if (include[i]) {
if (matched == false) {
String pattern = patterns[i];
matched = ALL.equals(pattern) || Regex.simpleMatch(pattern, alias);
}
} else if (matched) {
matched = Regex.simpleMatch(patterns[i], alias) == false;
}
}
if (matched) {
if (matcher.test(aliasInfo.getAlias())) {
filteredValues.add(aliasInfo);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ public void testFindAliases() {
.putAlias(AliasMetadata.builder("alias1").build())
.putAlias(AliasMetadata.builder("alias2").build())
)
.put(
IndexMetadata.builder("index2")
.settings(Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, IndexVersion.current()))
.numberOfShards(1)
.numberOfReplicas(0)
.putAlias(AliasMetadata.builder("alias2").build())
.putAlias(AliasMetadata.builder("alias3").build())
)
.build();

{
Expand All @@ -135,10 +143,12 @@ public void testFindAliases() {
}
{
GetAliasesRequest request = new GetAliasesRequest("alias*");
Map<String, List<AliasMetadata>> aliases = metadata.findAliases(request.aliases(), new String[] { "index" });
assertThat(aliases, aMapWithSize(1));
List<AliasMetadata> aliasMetadataList = aliases.get("index");
assertThat(aliasMetadataList, transformedItemsMatch(AliasMetadata::alias, contains("alias1", "alias2")));
Map<String, List<AliasMetadata>> aliases = metadata.findAliases(request.aliases(), new String[] { "index", "index2" });
assertThat(aliases, aMapWithSize(2));
List<AliasMetadata> indexAliasMetadataList = aliases.get("index");
assertThat(indexAliasMetadataList, transformedItemsMatch(AliasMetadata::alias, contains("alias1", "alias2")));
List<AliasMetadata> index2AliasMetadataList = aliases.get("index2");
assertThat(index2AliasMetadataList, transformedItemsMatch(AliasMetadata::alias, contains("alias2", "alias3")));
}
{
GetAliasesRequest request = new GetAliasesRequest("alias1");
Expand Down

0 comments on commit 31bea56

Please sign in to comment.