All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.camunda.operate.store.opensearch.OpensearchOperationStore 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.opensearch;

import static io.camunda.operate.store.opensearch.client.sync.OpenSearchRetryOperation.UPDATE_RETRY_COUNT;
import static io.camunda.operate.store.opensearch.dsl.QueryDSL.and;
import static io.camunda.operate.store.opensearch.dsl.QueryDSL.script;
import static io.camunda.operate.store.opensearch.dsl.QueryDSL.stringTerms;
import static io.camunda.operate.store.opensearch.dsl.QueryDSL.term;
import static io.camunda.operate.store.opensearch.dsl.RequestDSL.searchRequestBuilder;
import static io.camunda.operate.util.ExceptionHelper.withPersistenceException;

import io.camunda.operate.conditions.OpensearchCondition;
import io.camunda.operate.entities.BatchOperationEntity;
import io.camunda.operate.entities.OperationEntity;
import io.camunda.operate.entities.OperationState;
import io.camunda.operate.entities.OperationType;
import io.camunda.operate.exceptions.OperateRuntimeException;
import io.camunda.operate.exceptions.PersistenceException;
import io.camunda.operate.schema.templates.BatchOperationTemplate;
import io.camunda.operate.schema.templates.OperationTemplate;
import io.camunda.operate.store.BatchRequest;
import io.camunda.operate.store.OperationStore;
import io.camunda.operate.store.opensearch.client.sync.RichOpenSearchClient;
import io.camunda.operate.store.opensearch.dsl.RequestDSL;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import org.opensearch.client.opensearch._types.Refresh;
import org.opensearch.client.opensearch._types.query_dsl.Query;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;

@Conditional(OpensearchCondition.class)
@Component
public class OpensearchOperationStore implements OperationStore {
  private static final Logger LOGGER = LoggerFactory.getLogger(OpensearchOperationStore.class);
  @Autowired private RichOpenSearchClient richOpenSearchClient;

  @Autowired private OperationTemplate operationTemplate;

  @Autowired private BatchOperationTemplate batchOperationTemplate;

  @Autowired private BeanFactory beanFactory;

  @Override
  public Map getIndexNameForAliasAndIds(String alias, Collection ids) {
    return richOpenSearchClient.doc().getIndexNames(alias, ids);
  }

  @Override
  public List getOperationsFor(
      Long zeebeCommandKey,
      Long processInstanceKey,
      Long incidentKey,
      OperationType operationType) {
    if (processInstanceKey == null && zeebeCommandKey == null) {
      throw new OperateRuntimeException(
          "Wrong call to search for operation. Not enough parameters.");
    }

    final Query zeebeCommandKeyQ =
        zeebeCommandKey != null ? term(OperationTemplate.ZEEBE_COMMAND_KEY, zeebeCommandKey) : null;
    final Query processInstanceKeyQ =
        processInstanceKey != null
            ? term(OperationTemplate.PROCESS_INSTANCE_KEY, processInstanceKey)
            : null;
    final Query incidentKeyQ =
        incidentKey != null ? term(OperationTemplate.INCIDENT_KEY, incidentKey) : null;
    final Query operationTypeQ =
        operationType != null ? term(OperationTemplate.TYPE, operationType.name()) : null;
    final Query query =
        and(
            zeebeCommandKeyQ,
            processInstanceKeyQ,
            incidentKeyQ,
            operationTypeQ,
            stringTerms(
                OperationTemplate.STATE,
                List.of(OperationState.SENT.name(), OperationState.LOCKED.name())));
    final var searchRequestBuilder =
        searchRequestBuilder(operationTemplate.getAlias()).query(query).size(1);

    return richOpenSearchClient.doc().scrollValues(searchRequestBuilder, OperationEntity.class);
  }

  @Override
  public String add(BatchOperationEntity batchOperationEntity) throws PersistenceException {
    final var indexRequestBuilder =
        RequestDSL.indexRequestBuilder(
                batchOperationTemplate.getFullQualifiedName())
            .id(batchOperationEntity.getId())
            .document(batchOperationEntity);

    withPersistenceException(() -> richOpenSearchClient.doc().index(indexRequestBuilder));

    return batchOperationEntity.getId();
  }

  @Override
  public void update(OperationEntity operation, boolean refreshImmediately)
      throws PersistenceException {
    final Function errorMessageSupplier =
        e ->
            String.format(
                "Error preparing the query to update operation [%s] for process instance id [%s]",
                operation.getId(), operation.getProcessInstanceKey());
    final var updateRequestBuilder =
        RequestDSL.updateRequestBuilder(
                operationTemplate.getFullQualifiedName())
            .id(operation.getId())
            .doc(operation)
            .retryOnConflict(UPDATE_RETRY_COUNT);

    if (refreshImmediately) {
      updateRequestBuilder.refresh(Refresh.True);
    }

    withPersistenceException(
        () -> richOpenSearchClient.doc().update(updateRequestBuilder, errorMessageSupplier));
  }

  @Override
  public void updateWithScript(
      String index, String id, String script, Map parameters) {
    final Function errorMessageSupplier =
        e ->
            String.format(
                "Exception occurred, while executing update request with script for operation [%s]",
                id);
    final var updateRequestBuilder =
        RequestDSL.updateRequestBuilder(index)
            .id(id)
            .script(script(script, parameters))
            .retryOnConflict(UPDATE_RETRY_COUNT);

    richOpenSearchClient.doc().update(updateRequestBuilder, errorMessageSupplier);
  }

  @Override
  public BatchRequest newBatchRequest() {
    return beanFactory.getBean(BatchRequest.class);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy