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

io.camunda.zeebe.process.test.engine.InMemoryEngine Maven / Gradle / Ivy

Go to download

Test engine for running process tests. This a minimized version of the real Zeebe engine and should be used for testing purposes only.

There is a newer version: 8.7.0-alpha1
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 Zeebe Community License 1.1. You may not use this file
 * except in compliance with the Zeebe Community License 1.1.
 */
package io.camunda.zeebe.process.test.engine;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.camunda.zeebe.client.ZeebeClient;
import io.camunda.zeebe.client.impl.ZeebeObjectMapper;
import io.camunda.zeebe.db.ZeebeDb;
import io.camunda.zeebe.logstreams.log.LogStream;
import io.camunda.zeebe.process.test.api.RecordStreamSource;
import io.camunda.zeebe.process.test.api.ZeebeTestEngine;
import io.camunda.zeebe.protocol.ZbColumnFamilies;
import io.camunda.zeebe.scheduler.ActorScheduler;
import io.camunda.zeebe.scheduler.clock.ControlledActorClock;
import io.camunda.zeebe.stream.impl.StreamProcessor;
import io.grpc.Server;
import java.io.IOException;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class InMemoryEngine implements ZeebeTestEngine {

  private static final Logger LOG = LoggerFactory.getLogger(InMemoryEngine.class);

  private final Server grpcServer;
  private final StreamProcessor streamProcessor;
  private final GrpcToLogStreamGateway gateway;
  private final ZeebeDb database;
  private final LogStream logStream;
  private final ActorScheduler scheduler;
  private final RecordStreamSource recordStream;
  private final ControlledActorClock clock;
  private final EngineStateMonitor engineStateMonitor;

  public InMemoryEngine(
      final Server grpcServer,
      final StreamProcessor streamProcessor,
      final GrpcToLogStreamGateway gateway,
      final ZeebeDb database,
      final LogStream logStream,
      final ActorScheduler scheduler,
      final RecordStreamSource recordStream,
      final ControlledActorClock clock,
      final EngineStateMonitor engineStateMonitor) {
    this.grpcServer = grpcServer;
    this.streamProcessor = streamProcessor;
    this.gateway = gateway;
    this.database = database;
    this.logStream = logStream;
    this.scheduler = scheduler;
    this.recordStream = recordStream;
    this.clock = clock;
    this.engineStateMonitor = engineStateMonitor;
  }

  @Override
  public void start() {
    try {
      grpcServer.start();
      streamProcessor.openAsync(false).join();
    } catch (final IOException e) {
      LOG.error("Failed starting in memory engine", e);
      throw new RuntimeException(e);
    }
  }

  @Override
  public void stop() {
    try {
      grpcServer.shutdownNow();
      grpcServer.awaitTermination();
      streamProcessor.close();
      database.close();
      logStream.close();
      scheduler.stop();
    } catch (final Exception e) {
      LOG.error("Failed stopping in memory engine", e);
      throw new RuntimeException(e);
    }
  }

  @Override
  public RecordStreamSource getRecordStreamSource() {
    return recordStream;
  }

  @Override
  public ZeebeClient createClient() {
    return ZeebeClient.newClientBuilder()
        .applyEnvironmentVariableOverrides(false)
        .gatewayAddress(getGatewayAddress())
        .usePlaintext()
        .build();
  }

  @Override
  public ZeebeClient createClient(final ObjectMapper objectMapper) {
    return ZeebeClient.newClientBuilder()
        .withJsonMapper(new ZeebeObjectMapper(objectMapper))
        .applyEnvironmentVariableOverrides(false)
        .gatewayAddress(getGatewayAddress())
        .usePlaintext()
        .build();
  }

  @Override
  public String getGatewayAddress() {
    return gateway.getAddress();
  }

  @Override
  public void increaseTime(final Duration timeToAdd) {
    clock.addTime(timeToAdd);
  }

  @Override
  public void waitForIdleState(final Duration timeout)
      throws InterruptedException, TimeoutException {
    final CompletableFuture idleState = new CompletableFuture<>();

    engineStateMonitor.addOnIdleCallback(() -> idleState.complete(null));

    try {
      idleState.get(timeout.toMillis(), TimeUnit.MILLISECONDS);
    } catch (final ExecutionException e) {
      // Do nothing. ExecutionExceptions won't appear. The function only completes the future, which
      // in itself does not throw any exceptions.
    }
  }

  @Override
  public void waitForBusyState(final Duration timeout)
      throws InterruptedException, TimeoutException {
    final CompletableFuture processingState = new CompletableFuture<>();

    engineStateMonitor.addOnProcessingCallback(() -> processingState.complete(null));

    try {
      processingState.get(timeout.toMillis(), TimeUnit.MILLISECONDS);
    } catch (final ExecutionException e) {
      // Do nothing. ExecutionExceptions won't appear. The function only completes the future, which
      // in itself does not throw any exceptions.
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy