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

io.camunda.zeebe.shared.management.JobStreamEndpoint Maven / Gradle / Ivy

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 Camunda License 1.0. You may not use this file
 * except in compliance with the Camunda License 1.0.
 */
package io.camunda.zeebe.shared.management;

import io.atomix.cluster.MemberId;
import io.camunda.zeebe.protocol.impl.stream.job.JobActivationProperties;
import io.camunda.zeebe.transport.stream.api.ClientStream;
import io.camunda.zeebe.transport.stream.api.RemoteStreamInfo;
import io.camunda.zeebe.util.buffer.BufferUtil;
import java.time.Duration;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpoint;
import org.springframework.stereotype.Component;
import org.springframework.util.MimeTypeUtils;

/**
 * An actuator endpoint which allows viewing the current registered streams. Here {@code remote}
 * refers to {@link io.camunda.zeebe.transport.stream.api.RemoteStream} instances registered on the
 * broker, and {@code client} refers to all {@link ClientStream} instances registered on the
 * gateway.
 *
 * 

If running a broker with an embedded gateway, both can be viewed; otherwise, one or the other * will always be empty. */ @Component @WebEndpoint(id = "jobstreams") public final class JobStreamEndpoint { private static final Set TYPES = Set.of("remote", "client"); private final Service service; @Autowired public JobStreamEndpoint(final Service service) { this.service = Objects.requireNonNull(service, "must specify a job stream service"); } /** * Returns the complete list of remote and client job streams as an object with two keys: {@code * remote} and {@code client}. Both are collections of the job streams of the appropriate type. * *

This view is mostly used for human debugging to quickly correlate the state of a stream on * the gateway and brokers. */ @ReadOperation public WebEndpointResponse list() { return new WebEndpointResponse<>( new JobStreams(getRemoteStreams(), getClientStreams()), 200, MimeTypeUtils.APPLICATION_JSON); } /** * Returns either the list of {@code client} or {@code remote} job streams, based on the given * {@code type}. If the type is unknown, returns a 400 with a singleton map containing an error * field with an appropriate message. * * @param type the type of streams to return */ @ReadOperation public WebEndpointResponse list(final @Selector String type) { if (!TYPES.contains(type)) { return new WebEndpointResponse<>( Map.of("error", "No known stream type '%s'; should be one of %s".formatted(type, TYPES)), 400, MimeTypeUtils.APPLICATION_JSON); } final Collection streams = "client".equals(type) ? getClientStreams() : getRemoteStreams(); return new WebEndpointResponse<>(streams, 200, MimeTypeUtils.APPLICATION_JSON); } private Collection getRemoteStreams() { return transformRemote(service.remoteJobStreams()); } private Collection getClientStreams() { return transformClient(service.clientJobStreams()); } private Collection transformRemote( final Collection> streams) { return streams.stream().map(this::transformRemote).toList(); } private Collection transformClient( final Collection> streams) { return streams.stream().map(this::transformClient).toList(); } private RemoteJobStream transformRemote(final RemoteStreamInfo stream) { final var consumers = stream.consumers().stream() .map(id -> new RemoteStreamId(id.streamId(), id.receiver().id())) .toList(); return new RemoteJobStream( BufferUtil.bufferAsString(stream.streamType()), transform(stream.metadata()), consumers); } private ClientJobStream transformClient(final ClientStream stream) { // it's safe to cast any filtered member ID to an integer, since a client stream can only be // connected to a broker, and brokers always have integer node IDs final var brokers = stream.liveConnections().stream().map(MemberId::id).map(Integer::valueOf).toList(); return new ClientJobStream( BufferUtil.bufferAsString(stream.streamType()), stream.streamId(), transform(stream.metadata()), brokers); } private Metadata transform(final JobActivationProperties properties) { return new Metadata( BufferUtil.bufferAsString(properties.worker()), Duration.ofMillis(properties.timeout()), properties.fetchVariables().stream().map(BufferUtil::bufferAsString).toList(), properties.tenantIds()); } /** View model for the combined list of all remote and client job streams. */ public record JobStreams( Collection remote, Collection client) {} /** View model of a single remote job stream for JSON serialization */ public record RemoteJobStream( String jobType, Metadata metadata, Collection consumers) implements JobStream {} /** * View model of a client job stream for JSON serialization. The {@link #connectedTo()} collection * is the set of broker IDs this stream is registered on, from the gateway's point of view. */ public record ClientJobStream( String jobType, Object id, Metadata metadata, Collection connectedTo) implements JobStream {} /** View model for the {@link JobActivationProperties} of a job stream. */ public record Metadata( String worker, Duration timeout, Collection fetchVariables, Collection tenantIds) {} /** View model for a remote job stream ID */ public record RemoteStreamId(UUID id, String receiver) {} public interface Service { /** Returns the list of registered remote/broker job streams. */ Collection> remoteJobStreams(); /** Returns the list of registered client/gateway job streams. */ Collection> clientJobStreams(); } public interface JobStream { Metadata metadata(); String jobType(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy