All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.camunda.operate.store.elasticsearch.ElasticsearchImportStore Maven / Gradle / Ivy
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
* one or more contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright ownership.
* Licensed under the Camunda License 1.0. You may not use this file
* except in compliance with the Camunda License 1.0.
*/
package io.camunda.operate.store.elasticsearch;
import static io.camunda.operate.schema.indices.ImportPositionIndex.META_CONCURRENCY_MODE;
import static io.camunda.operate.util.ElasticsearchUtil.joinWithAnd;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.camunda.operate.Metrics;
import io.camunda.operate.conditions.ElasticsearchCondition;
import io.camunda.operate.entities.meta.ImportPositionEntity;
import io.camunda.operate.property.OperateProperties;
import io.camunda.operate.schema.IndexMapping;
import io.camunda.operate.schema.indices.ImportPositionIndex;
import io.camunda.operate.store.ImportStore;
import io.camunda.operate.util.Either;
import io.camunda.operate.util.ElasticsearchUtil;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.xcontent.XContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Conditional(ElasticsearchCondition.class)
@Component
public class ElasticsearchImportStore implements ImportStore {
private static final Logger LOGGER = LoggerFactory.getLogger(ElasticsearchImportStore.class);
@Autowired private ImportPositionIndex importPositionType;
@Autowired private RestHighLevelClient esClient;
@Autowired private RetryElasticsearchClient retryElasticsearchClient;
@Autowired
@Qualifier("operateObjectMapper")
private ObjectMapper objectMapper;
@Autowired private Metrics metrics;
@Autowired private OperateProperties operateProperties;
@Override
public ImportPositionEntity getImportPositionByAliasAndPartitionId(String alias, int partitionId)
throws IOException {
final QueryBuilder queryBuilder =
joinWithAnd(
termQuery(ImportPositionIndex.ALIAS_NAME, alias),
termQuery(ImportPositionIndex.PARTITION_ID, partitionId));
final SearchRequest searchRequest =
new SearchRequest(importPositionType.getAlias())
.source(new SearchSourceBuilder().query(queryBuilder).size(10));
final SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
final Iterator hitIterator = searchResponse.getHits().iterator();
ImportPositionEntity position =
new ImportPositionEntity().setAliasName(alias).setPartitionId(partitionId);
if (hitIterator.hasNext()) {
position =
ElasticsearchUtil.fromSearchHit(
hitIterator.next().getSourceAsString(), objectMapper, ImportPositionEntity.class);
}
LOGGER.debug(
"Latest loaded position for alias [{}] and partitionId [{}]: {}",
alias,
partitionId,
position);
return position;
}
@Override
public Either updateImportPositions(
List positions, List postImportPositions) {
var preparedBulkRequest = prepareBulkRequest(positions);
if (preparedBulkRequest.isLeft()) {
final var e = preparedBulkRequest.getLeft();
return Either.left(e);
}
preparedBulkRequest = addPostImportRequests(preparedBulkRequest.get(), postImportPositions);
if (preparedBulkRequest.isLeft()) {
final var e = preparedBulkRequest.getLeft();
return Either.left(e);
}
try {
final var bulkRequest = preparedBulkRequest.get();
withImportPositionTimer(
() -> {
ElasticsearchUtil.processBulkRequest(
esClient,
bulkRequest,
operateProperties.getElasticsearch().getBulkRequestMaxSizeInBytes());
return null;
});
return Either.right(true);
} catch (final Throwable e) {
LOGGER.error("Error occurred while persisting latest loaded position", e);
return Either.left(e);
}
}
@Override
public void setConcurrencyMode(final boolean concurrencyMode) {
retryElasticsearchClient.updateMetaField(
importPositionType, META_CONCURRENCY_MODE, concurrencyMode);
}
@Override
public boolean getConcurrencyMode() {
final String indexName = importPositionType.getFullQualifiedName();
final Map indexMappings =
retryElasticsearchClient.getIndexMappings(indexName);
if (indexMappings.get(indexName).getMetaProperties() == null) {
return false;
} else {
final Object concurrencyMode =
indexMappings.get(indexName).getMetaProperties().get(META_CONCURRENCY_MODE);
return concurrencyMode == null ? false : (boolean) concurrencyMode;
}
}
private void withImportPositionTimer(final Callable action) throws Exception {
metrics.getTimer(Metrics.TIMER_NAME_IMPORT_POSITION_UPDATE).recordCallable(action);
}
private Either prepareBulkRequest(
final List positions) {
final var bulkRequest = new BulkRequest();
if (positions.size() > 0) {
final var preparedUpdateRequests =
positions.stream().map(this::prepareUpdateRequest).collect(Either.collectorFoldingLeft());
if (preparedUpdateRequests.isLeft()) {
final var e = preparedUpdateRequests.getLeft();
return Either.left(e);
}
preparedUpdateRequests.get().forEach(bulkRequest::add);
}
return Either.right(bulkRequest);
}
private Either addPostImportRequests(
final BulkRequest bulkRequest, final List positions) {
if (positions.size() > 0) {
final var preparedUpdateRequests =
positions.stream()
.map(this::preparePostImportUpdateRequest)
.collect(Either.collectorFoldingLeft());
if (preparedUpdateRequests.isLeft()) {
final var e = preparedUpdateRequests.getLeft();
return Either.left(e);
}
preparedUpdateRequests.get().forEach(bulkRequest::add);
}
return Either.right(bulkRequest);
}
private Either preparePostImportUpdateRequest(
final ImportPositionEntity position) {
try {
final var index = importPositionType.getFullQualifiedName();
final var source = objectMapper.writeValueAsString(position);
final var updateFields = new HashMap();
updateFields.put(
ImportPositionIndex.POST_IMPORTER_POSITION, position.getPostImporterPosition());
final UpdateRequest updateRequest =
new UpdateRequest()
.index(index)
.id(position.getId())
.upsert(source, XContentType.JSON)
.doc(updateFields);
return Either.right(updateRequest);
} catch (final Exception e) {
LOGGER.error(
String.format(
"Error occurred while preparing request to update processed position for %s",
position.getAliasName()),
e);
return Either.left(e);
}
}
private Either prepareUpdateRequest(
final ImportPositionEntity position) {
try {
final var index = importPositionType.getFullQualifiedName();
final var source = objectMapper.writeValueAsString(position);
final var updateFields = new HashMap();
updateFields.put(ImportPositionIndex.POSITION, position.getPosition());
updateFields.put(ImportPositionIndex.FIELD_INDEX_NAME, position.getIndexName());
updateFields.put(ImportPositionIndex.SEQUENCE, position.getSequence());
final UpdateRequest updateRequest =
new UpdateRequest()
.index(index)
.id(position.getId())
.upsert(source, XContentType.JSON)
.doc(updateFields);
return Either.right(updateRequest);
} catch (final Exception e) {
LOGGER.error(
String.format(
"Error occurred while preparing request to update processed position for %s",
position.getAliasName()),
e);
return Either.left(e);
}
}
}