
org.apache.pulsar.functions.utils.SourceConfigUtils Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.pulsar.functions.utils;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import static org.apache.pulsar.functions.utils.FunctionCommon.convertFromCompressionType;
import static org.apache.pulsar.functions.utils.FunctionCommon.convertFromFunctionDetailsCompressionType;
import static org.apache.pulsar.functions.utils.FunctionCommon.convertProcessingGuarantee;
import static org.apache.pulsar.functions.utils.FunctionCommon.getSourceType;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.jodah.typetools.TypeResolver;
import org.apache.commons.lang3.StringUtils;
import org.apache.pulsar.common.functions.ProducerConfig;
import org.apache.pulsar.common.functions.Resources;
import org.apache.pulsar.common.io.BatchSourceConfig;
import org.apache.pulsar.common.io.ConnectorDefinition;
import org.apache.pulsar.common.io.SourceConfig;
import org.apache.pulsar.common.naming.TopicDomain;
import org.apache.pulsar.common.naming.TopicName;
import org.apache.pulsar.common.nar.NarClassLoader;
import org.apache.pulsar.common.util.ObjectMapperFactory;
import org.apache.pulsar.config.validation.ConfigValidation;
import org.apache.pulsar.functions.api.utils.IdentityFunction;
import org.apache.pulsar.functions.proto.Function;
import org.apache.pulsar.functions.proto.Function.FunctionDetails;
import org.apache.pulsar.functions.utils.io.ConnectorUtils;
import org.apache.pulsar.io.core.BatchSource;
import org.apache.pulsar.io.core.Source;
@Slf4j
public class SourceConfigUtils {
@Getter
@Setter
@AllArgsConstructor
public static class ExtractedSourceDetails {
private String sourceClassName;
private String typeArg;
}
public static FunctionDetails convert(SourceConfig sourceConfig, ExtractedSourceDetails sourceDetails)
throws IllegalArgumentException {
FunctionDetails.Builder functionDetailsBuilder = FunctionDetails.newBuilder();
boolean isBuiltin = !StringUtils.isEmpty(sourceConfig.getArchive()) && sourceConfig.getArchive()
.startsWith(org.apache.pulsar.common.functions.Utils.BUILTIN);
if (sourceConfig.getTenant() != null) {
functionDetailsBuilder.setTenant(sourceConfig.getTenant());
}
if (sourceConfig.getNamespace() != null) {
functionDetailsBuilder.setNamespace(sourceConfig.getNamespace());
}
if (sourceConfig.getName() != null) {
functionDetailsBuilder.setName(sourceConfig.getName());
}
functionDetailsBuilder.setRuntime(FunctionDetails.Runtime.JAVA);
if (sourceConfig.getParallelism() != null) {
functionDetailsBuilder.setParallelism(sourceConfig.getParallelism());
} else {
functionDetailsBuilder.setParallelism(1);
}
functionDetailsBuilder.setClassName(IdentityFunction.class.getName());
functionDetailsBuilder.setAutoAck(true);
if (sourceConfig.getProcessingGuarantees() != null) {
functionDetailsBuilder.setProcessingGuarantees(
convertProcessingGuarantee(sourceConfig.getProcessingGuarantees()));
}
// set source spec
Function.SourceSpec.Builder sourceSpecBuilder = Function.SourceSpec.newBuilder();
if (sourceDetails.getSourceClassName() != null) {
sourceSpecBuilder.setClassName(sourceDetails.getSourceClassName());
}
if (isBuiltin) {
String builtin = sourceConfig.getArchive().replaceFirst("^builtin://", "");
sourceSpecBuilder.setBuiltin(builtin);
}
Map configs = new HashMap<>();
if (sourceConfig.getConfigs() != null) {
configs.putAll(sourceConfig.getConfigs());
}
// Batch source handling
if (sourceConfig.getBatchSourceConfig() != null) {
configs.put(BatchSourceConfig.BATCHSOURCE_CONFIG_KEY,
new Gson().toJson(sourceConfig.getBatchSourceConfig()));
configs.put(BatchSourceConfig.BATCHSOURCE_CLASSNAME_KEY, sourceSpecBuilder.getClassName());
sourceSpecBuilder.setClassName("org.apache.pulsar.functions.source.batch.BatchSourceExecutor");
}
sourceSpecBuilder.setConfigs(new Gson().toJson(configs));
if (sourceConfig.getSecrets() != null && !sourceConfig.getSecrets().isEmpty()) {
functionDetailsBuilder.setSecretsMap(new Gson().toJson(sourceConfig.getSecrets()));
}
if (sourceDetails.getTypeArg() != null) {
sourceSpecBuilder.setTypeClassName(sourceDetails.getTypeArg());
}
functionDetailsBuilder.setSource(sourceSpecBuilder);
// set up sink spec.
// Sink spec classname should be empty so that the default pulsar sink will be used
Function.SinkSpec.Builder sinkSpecBuilder = Function.SinkSpec.newBuilder();
if (!org.apache.commons.lang3.StringUtils.isEmpty(sourceConfig.getSchemaType())) {
sinkSpecBuilder.setSchemaType(sourceConfig.getSchemaType());
}
if (!org.apache.commons.lang3.StringUtils.isEmpty(sourceConfig.getSerdeClassName())) {
sinkSpecBuilder.setSerDeClassName(sourceConfig.getSerdeClassName());
}
if (!isEmpty(sourceConfig.getTopicName())) {
sinkSpecBuilder.setTopic(sourceConfig.getTopicName());
}
if (sourceDetails.getTypeArg() != null) {
sinkSpecBuilder.setTypeClassName(sourceDetails.getTypeArg());
}
if (sourceConfig.getProducerConfig() != null) {
ProducerConfig conf = sourceConfig.getProducerConfig();
Function.ProducerSpec.Builder pbldr = Function.ProducerSpec.newBuilder();
if (conf.getMaxPendingMessages() != null) {
pbldr.setMaxPendingMessages(conf.getMaxPendingMessages());
}
if (conf.getMaxPendingMessagesAcrossPartitions() != null) {
pbldr.setMaxPendingMessagesAcrossPartitions(conf.getMaxPendingMessagesAcrossPartitions());
}
if (conf.getUseThreadLocalProducers() != null) {
pbldr.setUseThreadLocalProducers(conf.getUseThreadLocalProducers());
}
if (conf.getCryptoConfig() != null) {
pbldr.setCryptoSpec(CryptoUtils.convert(conf.getCryptoConfig()));
}
if (conf.getBatchBuilder() != null) {
pbldr.setBatchBuilder(conf.getBatchBuilder());
}
if (conf.getCompressionType() != null) {
pbldr.setCompressionType(convertFromCompressionType(conf.getCompressionType()));
} else {
pbldr.setCompressionType(Function.CompressionType.LZ4);
}
sinkSpecBuilder.setProducerSpec(pbldr.build());
}
if (sourceConfig.getBatchBuilder() != null) {
Function.ProducerSpec.Builder builder = sinkSpecBuilder.getProducerSpec() != null
? sinkSpecBuilder.getProducerSpec().toBuilder()
: Function.ProducerSpec.newBuilder();
sinkSpecBuilder.setProducerSpec(builder.setBatchBuilder(sourceConfig.getBatchBuilder()).build());
}
sinkSpecBuilder.setForwardSourceMessageProperty(true);
functionDetailsBuilder.setSink(sinkSpecBuilder);
// use default resources if resources not set
Resources resources = Resources.mergeWithDefault(sourceConfig.getResources());
Function.Resources.Builder bldr = Function.Resources.newBuilder();
bldr.setCpu(resources.getCpu());
bldr.setRam(resources.getRam());
bldr.setDisk(resources.getDisk());
functionDetailsBuilder.setResources(bldr);
if (!org.apache.commons.lang3.StringUtils.isEmpty(sourceConfig.getRuntimeFlags())) {
functionDetailsBuilder.setRuntimeFlags(sourceConfig.getRuntimeFlags());
}
functionDetailsBuilder.setComponentType(FunctionDetails.ComponentType.SOURCE);
if (!StringUtils.isEmpty(sourceConfig.getCustomRuntimeOptions())) {
functionDetailsBuilder.setCustomRuntimeOptions(sourceConfig.getCustomRuntimeOptions());
}
return FunctionConfigUtils.validateFunctionDetails(functionDetailsBuilder.build());
}
public static SourceConfig convertFromDetails(FunctionDetails functionDetails) {
SourceConfig sourceConfig = new SourceConfig();
sourceConfig.setTenant(functionDetails.getTenant());
sourceConfig.setNamespace(functionDetails.getNamespace());
sourceConfig.setName(functionDetails.getName());
sourceConfig.setParallelism(functionDetails.getParallelism());
sourceConfig.setProcessingGuarantees(
FunctionCommon.convertProcessingGuarantee(functionDetails.getProcessingGuarantees()));
Function.SourceSpec sourceSpec = functionDetails.getSource();
if (!StringUtils.isEmpty(sourceSpec.getClassName())) {
sourceConfig.setClassName(sourceSpec.getClassName());
}
if (!StringUtils.isEmpty(sourceSpec.getBuiltin())) {
sourceConfig.setArchive("builtin://" + sourceSpec.getBuiltin());
}
Map configMap =
extractSourceConfig(sourceSpec, FunctionCommon.getFullyQualifiedName(functionDetails));
if (configMap != null) {
BatchSourceConfig batchSourceConfig = extractBatchSourceConfig(configMap);
if (batchSourceConfig != null) {
sourceConfig.setBatchSourceConfig(batchSourceConfig);
if (configMap.containsKey(BatchSourceConfig.BATCHSOURCE_CLASSNAME_KEY)) {
if (!StringUtils.isEmpty((String) configMap.get(BatchSourceConfig.BATCHSOURCE_CLASSNAME_KEY))) {
sourceConfig.setClassName((String) configMap.get(BatchSourceConfig.BATCHSOURCE_CLASSNAME_KEY));
} else {
sourceConfig.setClassName(null);
}
}
}
configMap.remove(BatchSourceConfig.BATCHSOURCE_CONFIG_KEY);
configMap.remove(BatchSourceConfig.BATCHSOURCE_CLASSNAME_KEY);
sourceConfig.setConfigs(configMap);
}
if (!isEmpty(functionDetails.getSecretsMap())) {
Type type = new TypeToken
© 2015 - 2025 Weber Informatics LLC | Privacy Policy