com.yahoo.vespa.model.application.validation.change.StreamingSearchClusterChangeValidator Maven / Gradle / Ivy
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.model.application.validation.change;
import com.yahoo.config.model.api.ServiceInfo;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.documentmodel.NewDocumentType;
import com.yahoo.schema.derived.AttributeFields;
import com.yahoo.schema.document.Attribute;
import com.yahoo.vespa.model.AbstractService;
import com.yahoo.vespa.model.application.validation.Validation.ChangeContext;
import com.yahoo.vespa.model.application.validation.change.search.ChangeMessageBuilder;
import com.yahoo.vespa.model.application.validation.change.search.DocumentTypeChangeValidator;
import com.yahoo.vespa.model.content.cluster.ContentCluster;
import com.yahoo.vespa.model.search.DocumentDatabase;
import com.yahoo.vespa.model.search.SearchCluster;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* Validates the changes between all current and next streaming search clusters in a Vespa model.
*
* @author geirst
*/
public class StreamingSearchClusterChangeValidator implements ChangeValidator {
@Override
public void validate(ChangeContext context) {
context.previousModel().getContentClusters().forEach((clusterName, currentCluster) -> {
ContentCluster nextCluster = context.model().getContentClusters().get(clusterName);
if (nextCluster != null) {
if (currentCluster.getSearch().getSearchCluster() != null && nextCluster.getSearch().getSearchCluster() != null) {
validateStreamingCluster(currentCluster, currentCluster.getSearch().getSearchCluster(),
nextCluster, nextCluster.getSearch().getSearchCluster())
.forEach(context::require);
}
}
});
}
private static List validateStreamingCluster(ContentCluster currentCluster,
SearchCluster currentStreamingCluster,
ContentCluster nextCluster,
SearchCluster nextStreamingCluster) {
List result = new ArrayList<>();
for (DocumentDatabase currentDB : currentStreamingCluster.getDocumentDbs()) {
DocumentDatabase nextDB = nextStreamingCluster.getDocumentDB(currentDB.getName());
if (nextDB != null) {
result.addAll(validateDocumentDB(currentCluster, currentDB, nextCluster, nextDB));
}
}
return result;
}
private static List validateDocumentDB(ContentCluster currentCluster, DocumentDatabase currentDB,
ContentCluster nextCluster, DocumentDatabase nextDB) {
List result = new ArrayList<>();
result.addAll(validateDocumentTypeChanges(currentCluster.id(),
getDocumentType(currentCluster, currentDB),
getDocumentType(nextCluster, nextDB)));
result.addAll(validateAttributeFastAccessAdded(currentCluster.id(),
currentDB.getDerivedConfiguration().getAttributeFields(),
nextDB.getDerivedConfiguration().getAttributeFields()));
result.addAll(validateAttributeFastAccessRemoved(currentCluster.id(),
currentDB.getDerivedConfiguration().getAttributeFields(),
nextDB.getDerivedConfiguration().getAttributeFields()));
return modifyActions(result, getSearchNodeServices(nextCluster), nextDB.getName());
}
private static List validateDocumentTypeChanges(ClusterSpec.Id id,
NewDocumentType currentDocType,
NewDocumentType nextDocType) {
return new DocumentTypeChangeValidator(id, currentDocType, nextDocType).validate();
}
private static NewDocumentType getDocumentType(ContentCluster cluster, DocumentDatabase db) {
return cluster.getDocumentDefinitions().get(db.getName());
}
private static List validateAttributeFastAccessAdded(ClusterSpec.Id id,
AttributeFields currentAttributes,
AttributeFields nextAttributes) {
return validateAttributeFastAccessChanged(id, nextAttributes, currentAttributes, "add");
}
private static List validateAttributeFastAccessRemoved(ClusterSpec.Id id,
AttributeFields currentAttributes,
AttributeFields nextAttributes) {
return validateAttributeFastAccessChanged(id, currentAttributes, nextAttributes, "remove");
}
private static List validateAttributeFastAccessChanged(ClusterSpec.Id id,
AttributeFields lhsAttributes,
AttributeFields rhsAttributes,
String change) {
return lhsAttributes.attributes().stream()
.filter(attr -> attr.isFastAccess() &&
!hasFastAccessAttribute(attr.getName(), rhsAttributes))
.map(attr -> new VespaRestartAction(id, new ChangeMessageBuilder(attr.getName()).addChange(change + " fast-access attribute").build()))
.collect(Collectors.toList());
}
private static boolean hasFastAccessAttribute(String attrName, AttributeFields attributes) {
Attribute attr = attributes.getAttribute(attrName);
return (attr != null && attr.isFastAccess());
}
private static List getSearchNodeServices(ContentCluster cluster) {
return cluster.getSearch().getSearchNodes().stream()
.map(AbstractService::getServiceInfo)
.toList();
}
private static List modifyActions(List result,
List services,
String docTypeName) {
return result.stream()
.map(action -> action.modifyAction("Document type '" + docTypeName + "': " + action.getMessage(),
services, docTypeName))
.collect(Collectors.toList());
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy