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.zeebe.broker.system.partitions.ZeebePartitionAdminAccess 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.zeebe.broker.system.partitions;
import static java.util.Objects.requireNonNull;
import io.camunda.zeebe.broker.Loggers;
import io.camunda.zeebe.broker.partitioning.PartitionAdminAccess;
import io.camunda.zeebe.broker.system.configuration.FlowControlCfg;
import io.camunda.zeebe.engine.state.processing.DbBannedInstanceState;
import io.camunda.zeebe.logstreams.impl.flowcontrol.FlowControl;
import io.camunda.zeebe.logstreams.impl.flowcontrol.FlowControlLimits;
import io.camunda.zeebe.logstreams.log.LogStreamWriter;
import io.camunda.zeebe.logstreams.log.LogStreamWriter.WriteFailure;
import io.camunda.zeebe.logstreams.log.WriteContext;
import io.camunda.zeebe.protocol.impl.record.RecordMetadata;
import io.camunda.zeebe.protocol.impl.record.value.error.ErrorRecord;
import io.camunda.zeebe.protocol.record.RecordType;
import io.camunda.zeebe.protocol.record.RejectionType;
import io.camunda.zeebe.protocol.record.ValueType;
import io.camunda.zeebe.protocol.record.intent.ErrorIntent;
import io.camunda.zeebe.scheduler.ConcurrencyControl;
import io.camunda.zeebe.scheduler.future.ActorFuture;
import io.camunda.zeebe.stream.impl.records.RecordBatchEntry;
import io.camunda.zeebe.util.Either;
import java.io.IOException;
import java.util.Optional;
import org.slf4j.Logger;
class ZeebePartitionAdminAccess implements PartitionAdminAccess {
private static final Logger LOG = Loggers.SYSTEM_LOGGER;
private final ConcurrencyControl concurrencyControl;
private final int partitionId;
private final PartitionAdminControl adminControl;
ZeebePartitionAdminAccess(
final ConcurrencyControl concurrencyControl,
final int partitionId,
final PartitionAdminControl adminControl) {
this.concurrencyControl = requireNonNull(concurrencyControl);
this.partitionId = partitionId;
this.adminControl = requireNonNull(adminControl);
}
@Override
public Optional forPartition(final int partitionId) {
if (this.partitionId == partitionId) {
return Optional.of(this);
} else {
return Optional.empty();
}
}
@Override
public ActorFuture takeSnapshot() {
final ActorFuture completed = concurrencyControl.createFuture();
concurrencyControl.run(
() -> {
try {
adminControl.triggerSnapshot();
completed.complete(null);
} catch (final Exception e) {
completed.completeExceptionally(e);
}
});
return completed;
}
@Override
public ActorFuture pauseExporting() {
final ActorFuture completed = concurrencyControl.createFuture();
concurrencyControl.run(
() -> {
try {
final var pauseStatePersisted = adminControl.pauseExporting();
if (adminControl.getExporterDirector() != null && pauseStatePersisted) {
adminControl.getExporterDirector().pauseExporting().onComplete(completed);
} else {
completed.complete(null);
}
} catch (final IOException e) {
LOG.error("Could not pause exporting", e);
completed.completeExceptionally(e);
}
});
return completed;
}
@Override
public ActorFuture softPauseExporting() {
final ActorFuture completed = concurrencyControl.createFuture();
concurrencyControl.run(
() -> {
try {
final var softPauseStatePersisted = adminControl.softPauseExporting();
if (adminControl.getExporterDirector() != null && softPauseStatePersisted) {
adminControl.getExporterDirector().softPauseExporting().onComplete(completed);
} else {
completed.complete(null);
}
} catch (final IOException e) {
LOG.error("Could not soft pause exporting", e);
completed.completeExceptionally(e);
}
});
return completed;
}
@Override
public ActorFuture resumeExporting() {
final ActorFuture completed = concurrencyControl.createFuture();
concurrencyControl.run(
() -> {
try {
adminControl.resumeExporting();
if (adminControl.getExporterDirector() != null && adminControl.shouldExport()) {
adminControl.getExporterDirector().resumeExporting().onComplete(completed);
} else {
completed.complete(null);
}
} catch (final IOException e) {
LOG.error("Could not resume exporting", e);
completed.completeExceptionally(e);
}
});
return completed;
}
@Override
public ActorFuture pauseProcessing() {
final ActorFuture completed = concurrencyControl.createFuture();
concurrencyControl.run(
() -> {
try {
adminControl.pauseProcessing();
if (adminControl.getStreamProcessor() != null && !adminControl.shouldProcess()) {
adminControl.getStreamProcessor().pauseProcessing().onComplete(completed);
} else {
completed.complete(null);
}
} catch (final IOException e) {
LOG.error("Could not pause processing state", e);
completed.completeExceptionally(e);
}
});
return completed;
}
@Override
public ActorFuture resumeProcessing() {
final ActorFuture completed = concurrencyControl.createFuture();
concurrencyControl.run(
() -> {
try {
adminControl.resumeProcessing();
if (adminControl.getStreamProcessor() != null && adminControl.shouldProcess()) {
adminControl.getStreamProcessor().resumeProcessing();
}
completed.complete(null);
} catch (final IOException e) {
LOG.error("Could not resume processing", e);
completed.completeExceptionally(e);
}
});
return completed;
}
@Override
public ActorFuture banInstance(final long processInstanceKey) {
final ActorFuture future = concurrencyControl.createFuture();
concurrencyControl.run(
() -> {
try {
final var logStreamWriter = adminControl.getLogStream().newLogStreamWriter();
writeErrorEventAndBanInstance(processInstanceKey, logStreamWriter, future);
} catch (final Exception e) {
LOG.error(
"Failure on writing error record to ban instance {} onto the LogStream.",
processInstanceKey,
e);
future.completeExceptionally(e);
}
});
return future;
}
@Override
public ActorFuture configureFlowControl(final FlowControlCfg flowControlCfg) {
final ActorFuture future = concurrencyControl.createFuture();
concurrencyControl.run(
() -> {
try {
final FlowControl flowControl = adminControl.getLogStream().getFlowControl();
if (flowControlCfg.getWrite() != null) {
flowControl.setWriteRateLimit(flowControlCfg.getWrite().buildLimit());
}
if (flowControlCfg.getRequest() != null) {
flowControl.setRequestLimit(flowControlCfg.getRequest().buildLimit());
}
future.complete(null);
} catch (final Exception e) {
LOG.error(
"Failure on configuring the append limit of flow control with config {}.",
flowControlCfg,
e);
future.completeExceptionally(e);
}
});
return future;
}
@Override
public ActorFuture getFlowControlConfiguration() {
final ActorFuture future = concurrencyControl.createFuture();
concurrencyControl.run(
() -> {
final var flowControl = adminControl.getLogStream().getFlowControl();
try {
final FlowControlLimits limits =
new FlowControlLimits(
flowControl.getRequestLimit(), flowControl.getWriteRateLimit());
future.complete(limits);
} catch (final Exception e) {
LOG.error("Failure on getting the limit configuration of flow control.", e);
future.completeExceptionally(e);
}
});
return future;
}
private void writeErrorEventAndBanInstance(
final long processInstanceKey, final LogStreamWriter writer, final ActorFuture future) {
tryWriteErrorEvent(writer, processInstanceKey)
.ifRightOrLeft(
position -> {
LOG.info("Wrote error record on position {}", position);
// we only want to make the state change after we wrote the event
banInstanceInState(processInstanceKey);
LOG.info("Successfully banned instance with key {}", processInstanceKey);
future.complete(null);
},
writeFailure -> {
final String errorMsg =
String.format(
"Failure %s on writing error record to ban instance %d",
writeFailure, processInstanceKey);
future.completeExceptionally(new IllegalStateException(errorMsg));
LOG.error(errorMsg);
});
}
private void banInstanceInState(final long processInstanceKey) {
final var zeebeDb = adminControl.getZeebeDb();
final var context = zeebeDb.createContext();
final var dbBannedInstanceState = new DbBannedInstanceState(zeebeDb, context, partitionId);
dbBannedInstanceState.banProcessInstance(processInstanceKey);
}
private static Either tryWriteErrorEvent(
final LogStreamWriter writer, final long processInstanceKey) {
final var errorRecord = new ErrorRecord();
errorRecord.initErrorRecord(new Exception("Instance was banned from outside."), -1);
errorRecord.setProcessInstanceKey(processInstanceKey);
final var recordMetadata =
new RecordMetadata()
.recordType(RecordType.EVENT)
.valueType(ValueType.ERROR)
.intent(ErrorIntent.CREATED)
.recordVersion(RecordMetadata.DEFAULT_RECORD_VERSION)
.rejectionType(RejectionType.NULL_VAL)
.rejectionReason("");
final var entry =
RecordBatchEntry.createEntry(processInstanceKey, recordMetadata, -1, errorRecord);
return writer.tryWrite(WriteContext.internal(), entry);
}
}