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

io.camunda.exporter.handlers.ListViewProcessInstanceFromIncidentHandler Maven / Gradle / Ivy

There is a newer version: 8.7.0-alpha2
Show newest version
/*
 * 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.exporter.handlers;

import static io.camunda.webapps.schema.descriptors.operate.template.ListViewTemplate.TREE_PATH;
import static io.camunda.zeebe.protocol.record.intent.IncidentIntent.CREATED;

import io.camunda.exporter.cache.ExporterEntityCache;
import io.camunda.exporter.cache.process.CachedProcessEntity;
import io.camunda.exporter.store.BatchRequest;
import io.camunda.exporter.utils.ProcessCacheUtil;
import io.camunda.webapps.operate.TreePath;
import io.camunda.webapps.schema.entities.operate.listview.ProcessInstanceForListViewEntity;
import io.camunda.zeebe.protocol.record.Record;
import io.camunda.zeebe.protocol.record.ValueType;
import io.camunda.zeebe.protocol.record.value.IncidentRecordValue;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Handler will update process instances with `treePath` values from the incident */
public class ListViewProcessInstanceFromIncidentHandler
    implements ExportHandler {

  private static final Logger LOGGER =
      LoggerFactory.getLogger(ListViewProcessInstanceFromIncidentHandler.class);

  private final String indexName;
  private final ExporterEntityCache processCache;

  public ListViewProcessInstanceFromIncidentHandler(
      final String indexName, final ExporterEntityCache processCache) {
    this.indexName = indexName;
    this.processCache = processCache;
  }

  @Override
  public ValueType getHandledValueType() {
    return ValueType.INCIDENT;
  }

  @Override
  public Class getEntityType() {
    return ProcessInstanceForListViewEntity.class;
  }

  @Override
  public boolean handlesRecord(final Record record) {
    return record.getIntent().equals(CREATED);
  }

  @Override
  public List generateIds(final Record record) {
    final List> elementInstancePath = record.getValue().getElementInstancePath();
    // every element is a list of keys, the first key is process instance key
    return elementInstancePath.stream().map(keys -> String.valueOf(keys.get(0))).toList();
  }

  @Override
  public ProcessInstanceForListViewEntity createNewEntity(final String id) {
    return new ProcessInstanceForListViewEntity().setId(id);
  }

  @Override
  public void updateEntity(
      final Record record, final ProcessInstanceForListViewEntity entity) {

    final IncidentRecordValue value = record.getValue();
    final List> elementInstancePath = value.getElementInstancePath();
    final List callingElementPath = value.getCallingElementPath();
    final List processDefinitionPath = value.getProcessDefinitionPath();

    final Long processInstanceKey = Long.valueOf(entity.getId());

    // example of how the tree path is built when current instance is on the third level of calling
    // hierarchy:
    // PI_/FN_/FNI_/
    // PI_/FN_/FNI_/PI_
    final TreePath treePath = new TreePath();
    for (int i = 0; i < elementInstancePath.size(); i++) {
      final List keysWithinOnePI = elementInstancePath.get(i);
      treePath.appendProcessInstance(keysWithinOnePI.get(0));
      if (keysWithinOnePI.get(0).equals(processInstanceKey)) {
        // we reached the leaf of the tree path, when we reached current processInstanceKey
        break;
      }
      final var callActivityId =
          ProcessCacheUtil.getCallActivityId(
              processCache, processDefinitionPath.get(i), callingElementPath.get(i));
      if (callActivityId.isPresent()) {
        treePath.appendFlowNode(callActivityId.get());
      } else {
        LOGGER.warn(
            "No process found in cache. TreePath won't contain proper callActivityId. processInstanceKey: {}, processDefinitionKey: {}, incidentKey: {}",
            processInstanceKey,
            processDefinitionPath.get(i),
            record.getKey());
        treePath.appendFlowNode(String.valueOf(callingElementPath.get(i)));
      }
      treePath.appendFlowNodeInstance(String.valueOf(keysWithinOnePI.get(1)));
    }
    entity.setTreePath(treePath.toString());
  }

  @Override
  public void flush(
      final ProcessInstanceForListViewEntity entity, final BatchRequest batchRequest) {

    final Map updateFields = new LinkedHashMap<>();
    updateFields.put(TREE_PATH, entity.getTreePath());

    batchRequest.upsert(indexName, entity.getId(), entity, updateFields);
  }

  @Override
  public String getIndexName() {
    return indexName;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy