Skip to content

Commit

Permalink
Refresh entities mapping cache.
Browse files Browse the repository at this point in the history
Signed-off-by: Youssef Aouichaoui <[email protected]>
  • Loading branch information
youssef3wi committed Sep 6, 2024
1 parent ce3a615 commit 9b66c69
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.springframework.data.elasticsearch.core.IndexInformation;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.ResourceUtil;
import org.springframework.data.elasticsearch.core.cluster.ClusterMapping;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.index.*;
Expand Down Expand Up @@ -81,6 +82,8 @@ public IndicesTemplate(ElasticsearchIndicesClient client, ClusterTemplate cluste
this.boundClass = boundClass;
this.boundIndex = null;

// cache entities metadata
refreshEntitiesMapping();
}

public IndicesTemplate(ElasticsearchIndicesClient client, ClusterTemplate clusterTemplate,
Expand All @@ -96,6 +99,8 @@ public IndicesTemplate(ElasticsearchIndicesClient client, ClusterTemplate cluste
this.boundClass = null;
this.boundIndex = boundIndex;

// cache entities metadata
refreshEntitiesMapping();
}

protected Class<?> checkForBoundClass() {
Expand Down Expand Up @@ -145,6 +150,8 @@ protected boolean doCreate(IndexCoordinates indexCoordinates, Map<String, Object

CreateIndexRequest createIndexRequest = requestConverter.indicesCreateRequest(indexSettings);
CreateIndexResponse createIndexResponse = execute(client -> client.create(createIndexRequest));
// refresh cached mappings
refreshEntitiesMapping();
return Boolean.TRUE.equals(createIndexResponse.acknowledged());
}

Expand Down Expand Up @@ -241,6 +248,45 @@ public Map<String, Object> getMapping() {
return responseConverter.indicesGetMapping(getMappingResponse, indexCoordinates);
}

@Override
public ClusterMapping getClusterMapping() {
GetMappingRequest getMappingRequest = requestConverter.indicesGetMappingRequest(IndexCoordinates.of("*"));
GetMappingResponse getMappingResponse = execute(client -> client.getMapping(getMappingRequest));

return responseConverter.indicesGetMapping(getMappingResponse);
}

/**
* Refreshes the mapping of entities.
* <p>
* This method is responsible for retrieving and updating the metadata related to the entities.
*/
private void refreshEntitiesMapping() {
ClusterMapping clusterMapping = getClusterMapping();
for (ClusterMapping.ClusterMappingEntry mappingEntry : clusterMapping) {
// Get entity
Class<?> entity = null;
for (ElasticsearchPersistentEntity<?> persistentEntity : this.elasticsearchConverter.getMappingContext().getPersistentEntities()) {
if (mappingEntry.getName().equals(persistentEntity.getIndexCoordinates().getIndexName())) {
entity = persistentEntity.getType();

break;
}
}

if (entity == null) {
continue;
}

if (mappingEntry.getMappings().containsKey("dynamic_templates")) {
Object dynamicTemplates = mappingEntry.getMappings().get("dynamic_templates");
if (dynamicTemplates instanceof List<?> value) {
getRequiredPersistentEntity(entity).buildDynamicTemplates(value);
}
}
}
}

@Override
public Settings createSettings() {
return createSettings(checkForBoundClass());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.springframework.data.elasticsearch.core.IndexInformation;
import org.springframework.data.elasticsearch.core.ReactiveIndexOperations;
import org.springframework.data.elasticsearch.core.ReactiveResourceUtil;
import org.springframework.data.elasticsearch.core.cluster.ClusterMapping;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.index.*;
Expand Down Expand Up @@ -218,6 +219,14 @@ public Mono<Document> getMapping() {
return getMappingResponse.map(response -> responseConverter.indicesGetMapping(response, indexCoordinates));
}

@Override
public Mono<ClusterMapping> getClusterMapping() {
GetMappingRequest getMappingRequest = requestConverter.indicesGetMappingRequest(IndexCoordinates.of("*"));
Mono<GetMappingResponse> getMappingResponse = Mono.from(execute(client -> client.getMapping(getMappingRequest)));

return getMappingResponse.map(responseConverter::indicesGetMapping);
}

@Override
public Mono<Settings> createSettings() {
return createSettings(checkForBoundClass());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import org.springframework.data.elasticsearch.core.IndexInformation;
import org.springframework.data.elasticsearch.core.MultiGetItem;
import org.springframework.data.elasticsearch.core.cluster.ClusterHealth;
import org.springframework.data.elasticsearch.core.cluster.ClusterMapping;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.index.AliasData;
import org.springframework.data.elasticsearch.core.index.Settings;
Expand Down Expand Up @@ -213,6 +214,16 @@ public Document indicesGetMapping(GetMappingResponse getMappingResponse, IndexCo
return Document.parse(toJson(indexMappingRecord.mappings(), jsonpMapper));
}

public ClusterMapping indicesGetMapping(GetMappingResponse getMappingResponse) {
ClusterMapping.Builder builder = ClusterMapping.builder();
for (String indexName : getMappingResponse.result().keySet()) {
Map<String, Object> mappings = indicesGetMapping(getMappingResponse, IndexCoordinates.of(indexName));
builder.withMapping(ClusterMapping.ClusterMappingEntry.builder(indexName).withMappings(mappings).build());
}

return builder.build();
}

public List<IndexInformation> indicesGetIndexInformations(GetIndexResponse getIndexResponse) {

Assert.notNull(getIndexResponse, "getIndexResponse must not be null");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -603,15 +602,6 @@ protected <T> SearchDocumentResponse.EntityCreator<T> getEntityCreator(ReadDocum
// region Entity callbacks
protected <T> T maybeCallbackBeforeConvert(T entity, IndexCoordinates index) {

// get entity metadata
Map<String, Object> mapping = indexOps(index).getMapping();
if (mapping.containsKey("dynamic_templates")) {
Object dynamicTemplates = mapping.get("dynamic_templates");
if (dynamicTemplates instanceof List<?> value) {
getRequiredPersistentEntity(entity.getClass()).buildDynamicTemplates(value);
}
}

if (entityCallbacks != null) {
return entityCallbacks.callback(BeforeConvertCallback.class, entity, index);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.Map;
import java.util.Set;

import org.springframework.data.elasticsearch.core.cluster.ClusterMapping;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.index.*;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
Expand Down Expand Up @@ -144,6 +145,13 @@ default boolean putMapping(Class<?> clazz) {
*/
Map<String, Object> getMapping();

/**
* Get mappings of all indices in a cluster.
*
* @return Retrieve the mappings for all indices within a cluster.
*/
ClusterMapping getClusterMapping();

// endregion

// region settings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.springframework.data.elasticsearch.core;

import org.springframework.data.elasticsearch.core.cluster.ClusterMapping;
import reactor.core.publisher.Mono;

import java.util.List;
Expand Down Expand Up @@ -96,6 +97,11 @@ public Map<String, Object> getMapping() {
return Objects.requireNonNull(reactiveIndexOperations.getMapping().block());
}

@Override
public ClusterMapping getClusterMapping() {
return Objects.requireNonNull(reactiveIndexOperations.getClusterMapping().block());
}

@Override
public Settings createSettings() {
return Objects.requireNonNull(reactiveIndexOperations.createSettings().block());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.springframework.data.elasticsearch.core;

import org.springframework.data.elasticsearch.core.cluster.ClusterMapping;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

Expand Down Expand Up @@ -144,6 +145,13 @@ default Mono<Boolean> putMapping(Class<?> clazz) {
* @return the mapping
*/
Mono<Document> getMapping();

/**
* Get mappings of all indices in a cluster.
*
* @return Retrieve the mappings for all indices within a cluster.
*/
Mono<ClusterMapping> getClusterMapping();
// endregion

// region settings
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright 2024 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.core.cluster;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.jetbrains.annotations.NotNull;

/**
* Retrieves mapping definitions of all indices in the cluster.
*
* @author Youssef Aouichaoui
* @since 5.4
*/
public class ClusterMapping implements Iterable<ClusterMapping.ClusterMappingEntry> {
private final List<ClusterMappingEntry> mappings;

private ClusterMapping(Builder builder) {
this.mappings = builder.mappings;
}

@NotNull
@Override
public Iterator<ClusterMappingEntry> iterator() {
return mappings.iterator();
}

public static Builder builder() {
return new Builder();
}

public static class ClusterMappingEntry {
private final String name;
private final Map<String, Object> mappings;

private ClusterMappingEntry(Builder builder) {
this.name = builder.name;
this.mappings = builder.mappings;
}

public String getName() {
return name;
}

public Map<String, Object> getMappings() {
return Collections.unmodifiableMap(mappings);
}

public static Builder builder(String name) {
return new Builder(name);
}

public static class Builder {
private final String name;
private final Map<String, Object> mappings = new HashMap<>();

private Builder(String name) {
this.name = name;
}

public Builder withMappings(Map<String, Object> mappings) {
this.mappings.putAll(mappings);

return this;
}

public ClusterMappingEntry build() {
return new ClusterMappingEntry(this);
}
}
}

public static class Builder {
private final List<ClusterMappingEntry> mappings = new ArrayList<>();

private Builder() {}

public Builder withMapping(ClusterMappingEntry entry) {
mappings.add(entry);

return this;
}

public ClusterMapping build() {
return new ClusterMapping(this);
}
}
}

0 comments on commit 9b66c69

Please sign in to comment.