Merge pull request #1272 from eolivelli/impl/venice-adapter

[adapter-venice] Introduce new VeniceDB adapter
This commit is contained in:
Jonathan Shook 2023-05-18 15:17:53 -05:00 committed by GitHub
commit b8de62a0e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 717 additions and 1 deletions

127
adapter-venice/pom.xml Normal file
View File

@ -0,0 +1,127 @@
<!--
~ Copyright (c) 2023 nosqlbench
~
~ Licensed 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>adapter-venice</artifactId>
<packaging>jar</packaging>
<parent>
<artifactId>mvn-defaults</artifactId>
<groupId>io.nosqlbench</groupId>
<version>${revision}</version>
<relativePath>../mvn-defaults</relativePath>
</parent>
<name>${project.artifactId}</name>
<description>
A VeniceDB driver for nosqlbench. This provides the ability to read from VeniceDB.
</description>
<properties>
<venice.version>0.4.17-alpha-9</venice.version>
</properties>
<dependencies>
<!-- core dependencies -->
<dependency>
<groupId>io.nosqlbench</groupId>
<artifactId>engine-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>io.nosqlbench</groupId>
<artifactId>adapters-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.linkedin.venice</groupId>
<artifactId>venice-client-common</artifactId>
<version>${venice.version}</version>
<exclusions>
<exclusion>
<groupId>org.sonatype.oss</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.helix</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.conscrypt</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.linkedin.venice</groupId>
<artifactId>venice-thin-client</artifactId>
<version>${venice.version}</version>
<exclusions>
<exclusion>
<groupId>org.sonatype.oss</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.helix</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.conscrypt</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<repositories>
<repository>
<id>datastax-public</id>
<name>DataStax Public Repository</name>
<layout>default</layout>
<url>https://repo.datastax.com/datastax-public-releases-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
<repository>
<id>linkedin-oss</id>
<url>https://linkedin.jfrog.io/artifactory/open-source</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
</project>

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2022 nosqlbench
*
* Licensed 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 io.nosqlbench.adapter.venice;
import io.nosqlbench.adapter.venice.ops.VeniceOp;
import io.nosqlbench.api.config.standard.NBConfigModel;
import io.nosqlbench.api.config.standard.NBConfiguration;
import io.nosqlbench.engine.api.activityimpl.OpMapper;
import io.nosqlbench.engine.api.activityimpl.uniform.BaseDriverAdapter;
import io.nosqlbench.engine.api.activityimpl.uniform.DriverAdapter;
import io.nosqlbench.engine.api.activityimpl.uniform.DriverSpaceCache;
import io.nosqlbench.nb.annotations.Service;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.function.Function;
@Service(value = DriverAdapter.class, selector = "venice")
public class VeniceDriverAdapter extends BaseDriverAdapter<VeniceOp, VeniceSpace> {
private final static Logger logger = LogManager.getLogger(VeniceDriverAdapter.class);
@Override
public OpMapper<VeniceOp> getOpMapper() {
DriverSpaceCache<? extends VeniceSpace> spaceCache = getSpaceCache();
NBConfiguration adapterConfig = getConfiguration();
return new VeniceOpMapper(this, adapterConfig, spaceCache);
}
@Override
public Function<String, ? extends VeniceSpace> getSpaceInitializer(NBConfiguration cfg) {
return (s) -> new VeniceSpace(s, cfg);
}
@Override
public NBConfigModel getConfigModel() {
return super.getConfigModel().add(VeniceSpace.getConfigModel());
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2022 nosqlbench
*
* Licensed 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 io.nosqlbench.adapter.venice;
import io.nosqlbench.adapter.venice.dispensers.*;
import io.nosqlbench.adapter.venice.ops.VeniceOp;
import io.nosqlbench.api.config.standard.NBConfiguration;
import io.nosqlbench.engine.api.activityimpl.OpDispenser;
import io.nosqlbench.engine.api.activityimpl.OpMapper;
import io.nosqlbench.engine.api.activityimpl.uniform.DriverAdapter;
import io.nosqlbench.engine.api.activityimpl.uniform.DriverSpaceCache;
import io.nosqlbench.engine.api.templating.ParsedOp;
import io.nosqlbench.engine.api.templating.TypeAndTarget;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class VeniceOpMapper implements OpMapper<VeniceOp> {
private final static Logger logger = LogManager.getLogger(VeniceOpMapper.class);
private final NBConfiguration cfg;
private final DriverSpaceCache<? extends VeniceSpace> spaceCache;
private final DriverAdapter adapter;
public VeniceOpMapper(DriverAdapter adapter, NBConfiguration cfg, DriverSpaceCache<? extends VeniceSpace> spaceCache) {
this.cfg = cfg;
this.spaceCache = spaceCache;
this.adapter = adapter;
}
@Override
public OpDispenser<? extends VeniceOp> apply(ParsedOp op) {
String spaceName = op.getStaticConfigOr("space", "default");
VeniceSpace veniceSpace = spaceCache.get(spaceName);
/*
* If the user provides a body element, then they want to provide the JSON or
* a data structure that can be converted into JSON, bypassing any further
* specialized type-checking or op-type specific features
*/
if (op.isDefined("body")) {
throw new RuntimeException("This mode is reserved for later. Do not use the 'body' op field.");
}
else {
TypeAndTarget<VeniceOpType, String> opType = op.getTypeAndTarget(VeniceOpType.class, String.class);
return switch (opType.enumId) {
case ReadSingleKey ->
new ReadSingleKeyOpDispenser(adapter, op, veniceSpace);
};
}
}
}

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2022 nosqlbench
*
* Licensed 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 io.nosqlbench.adapter.venice;
public enum VeniceOpType {
// read a single key
ReadSingleKey
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2022 nosqlbench
*
* Licensed 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 io.nosqlbench.adapter.venice;
import com.linkedin.venice.client.store.AvroGenericStoreClient;
import com.linkedin.venice.client.store.ClientConfig;
import com.linkedin.venice.client.store.ClientFactory;
import io.nosqlbench.api.config.standard.ConfigModel;
import io.nosqlbench.api.config.standard.NBConfigModel;
import io.nosqlbench.api.config.standard.NBConfiguration;
import io.nosqlbench.api.config.standard.Param;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class VeniceSpace implements AutoCloseable {
private final static Logger logger = LogManager.getLogger(VeniceSpace.class);
private final String spaceName;
private final NBConfiguration cfg;
private final String routerUrl;
private final String storeName;
private long veniceActivityStartTimeMills;
private final String token;
private AvroGenericStoreClient<Object, Object> client;
public VeniceSpace(String spaceName, NBConfiguration cfg) {
this.spaceName = spaceName;
this.cfg = cfg;
this.routerUrl = cfg.get("router_url");
this.storeName = cfg.get("store_name");
this.token = cfg.get("token");
this.veniceActivityStartTimeMills = System.currentTimeMillis();
this.initializeSpace();
}
@Override
public void close() {
shutdownSpace();
}
public static NBConfigModel getConfigModel() {
return ConfigModel.of(VeniceSpace.class)
.add(Param.defaultTo("router_url", "http://localhost:7777")
.setDescription("Venice Router URL."))
.add(Param.defaultTo("store_name", "store1")
.setDescription("Name of the Venice store"))
.add(Param.defaultTo("token", "")
.setDescription("JWT Token Authentication"))
.asReadOnly();
}
public AvroGenericStoreClient<Object, Object> getClient() {
return client;
}
public void initializeSpace() {
ClientConfig clientConfig = ClientConfig.defaultGenericClientConfig(storeName);
clientConfig.setVeniceURL(routerUrl);
clientConfig.setForceClusterDiscoveryAtStartTime(true);
clientConfig.setToken(token);
client = ClientFactory.getAndStartGenericAvroClient(clientConfig);
}
public void shutdownSpace() {
try {
client.close();
}
catch (Exception e) {
logger.error("Unexpected error when shutting down NB S4J space.", e);
}
}
public long getVeniceActivityStartTimeMills() {
return veniceActivityStartTimeMills;
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2022 nosqlbench
*
* Licensed 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 io.nosqlbench.adapter.venice.dispensers;
import io.nosqlbench.adapter.venice.VeniceSpace;
import io.nosqlbench.adapter.venice.ops.ReadSingleKeyOp;
import io.nosqlbench.engine.api.activityimpl.uniform.DriverAdapter;
import io.nosqlbench.engine.api.templating.ParsedOp;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.LongFunction;
public class ReadSingleKeyOpDispenser extends VeniceBaseOpDispenser {
private final static Logger logger = LogManager.getLogger("ReadSingleKeyOpDispenser");
private final LongFunction<String> keyStrFunc;
private static final String KEY_OP_PARAM = "key";
public ReadSingleKeyOpDispenser(DriverAdapter adapter,
ParsedOp op,
VeniceSpace s4jSpace) {
super(adapter, op, s4jSpace);
this.keyStrFunc = lookupMandtoryStrOpValueFunc(KEY_OP_PARAM);
}
@Override
public ReadSingleKeyOp apply(long cycle) {
String key = keyStrFunc.apply(cycle);
return new ReadSingleKeyOp(
veniceAdapterMetrics,
veniceSpace,
key);
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2023 nosqlbench
*
* Licensed 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 io.nosqlbench.adapter.venice.dispensers;
import io.nosqlbench.adapter.venice.VeniceSpace;
import io.nosqlbench.adapter.venice.ops.VeniceOp;
import io.nosqlbench.adapter.venice.util.*;
import io.nosqlbench.engine.api.activityimpl.BaseOpDispenser;
import io.nosqlbench.engine.api.activityimpl.uniform.DriverAdapter;
import io.nosqlbench.engine.api.templating.ParsedOp;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.*;
import java.util.function.LongFunction;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public abstract class VeniceBaseOpDispenser extends BaseOpDispenser<VeniceOp, VeniceSpace> {
private static final Logger logger = LogManager.getLogger("VeniceBaseOpDispenser");
protected final ParsedOp parsedOp;
protected final VeniceSpace veniceSpace;
protected final VeniceAdapterMetrics veniceAdapterMetrics;
protected VeniceBaseOpDispenser(DriverAdapter adapter,
ParsedOp op,
VeniceSpace veniceSpace) {
super(adapter, op);
this.parsedOp = op;
this.veniceSpace = veniceSpace;
this.veniceAdapterMetrics = new VeniceAdapterMetrics(this);
veniceAdapterMetrics.initVeniceAdapterInstrumentation();
}
public VeniceSpace getVeniceSpace() { return veniceSpace; }
public VeniceAdapterMetrics getVeniceAdapterMetrics() { return veniceAdapterMetrics; }
// Mandatory Op parameter. Throw an error if not specified or having empty value
protected LongFunction<String> lookupMandtoryStrOpValueFunc(String paramName) {
LongFunction<String> stringLongFunction;
stringLongFunction = parsedOp.getAsRequiredFunction(paramName, String.class);
logger.info("{}: {}", paramName, stringLongFunction.apply(0));
return stringLongFunction;
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2022 nosqlbench
*
* Licensed 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 io.nosqlbench.adapter.venice.ops;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Timer;
import com.linkedin.venice.client.store.AvroGenericStoreClient;
import io.nosqlbench.adapter.venice.VeniceSpace;
import io.nosqlbench.adapter.venice.util.VeniceAdapterMetrics;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.concurrent.CompletableFuture;
public class ReadSingleKeyOp extends VeniceOp {
private final static Logger logger = LogManager.getLogger("ReadSingleKeyOp");
private final AvroGenericStoreClient<Object, Object> client;
private final String key;
private final Timer executeTimer;
private Counter foundCounter;
private Counter notFoundCounter;
public ReadSingleKeyOp(VeniceAdapterMetrics veniceAdapterMetrics,
VeniceSpace veniceSpace,
String key) {
super(veniceAdapterMetrics, veniceSpace);
this.client = veniceSpace.getClient();
this.key = key;
this.executeTimer = veniceAdapterMetrics.getExecuteTimer();
this.foundCounter = veniceAdapterMetrics.getFoundCounter();
this.notFoundCounter = veniceAdapterMetrics.getNotFoundCounter();
}
@Override
public Object apply(long value) {
Object callValue;
try (Timer.Context time = executeTimer.time();) {
CompletableFuture<Object> handle = client.get(key);
callValue = handle.join();
if (logger.isDebugEnabled()) {
logger.debug("ReadSingleKeyOp key={} value={}", key, callValue);
}
}
if (callValue != null) {
foundCounter.inc();
} else {
notFoundCounter.inc();
}
return null;
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2022 nosqlbench
*
* Licensed 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 io.nosqlbench.adapter.venice.ops;
import io.nosqlbench.adapter.venice.VeniceSpace;
import io.nosqlbench.adapter.venice.util.VeniceAdapterMetrics;
import io.nosqlbench.engine.api.activityimpl.uniform.flowtypes.CycleOp;
public abstract class VeniceOp implements CycleOp<Object> {
protected VeniceAdapterMetrics veniceAdapterMetrics;
protected final VeniceSpace veniceSpace;
protected final long veniceOpStartTimeMills;
public VeniceOp(
VeniceAdapterMetrics veniceAdapterMetrics,
VeniceSpace veniceSpace)
{
this.veniceAdapterMetrics = veniceAdapterMetrics;
this.veniceSpace = veniceSpace;
this.veniceOpStartTimeMills = veniceSpace.getVeniceActivityStartTimeMills();
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2022-2023 nosqlbench
*
* Licensed 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 io.nosqlbench.adapter.venice.util;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Timer;
import io.nosqlbench.adapter.venice.dispensers.VeniceBaseOpDispenser;
import io.nosqlbench.api.config.NBLabeledElement;
import io.nosqlbench.api.config.NBLabels;
import io.nosqlbench.api.engine.metrics.ActivityMetrics;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class VeniceAdapterMetrics {
private static final Logger logger = LogManager.getLogger("VeniceAdapterMetrics");
private Timer executeTimer;
private Counter foundCounter;
private Counter notFoundCounter;
private final VeniceBaseOpDispenser veniceBaseOpDispenser;
public VeniceAdapterMetrics(VeniceBaseOpDispenser veniceBaseOpDispenser) {
this.veniceBaseOpDispenser = veniceBaseOpDispenser;
}
public String getName() {
return "VeniceAdapterMetrics";
}
public void initVeniceAdapterInstrumentation() {
this.executeTimer =
ActivityMetrics.timer(
veniceBaseOpDispenser,"execute",
ActivityMetrics.DEFAULT_HDRDIGITS);
this.foundCounter =
ActivityMetrics.counter(
veniceBaseOpDispenser,"found");
this.notFoundCounter =
ActivityMetrics.counter(
veniceBaseOpDispenser, "notFound");
}
public Timer getExecuteTimer() { return executeTimer; }
public Counter getFoundCounter() {
return foundCounter;
}
public Counter getNotFoundCounter() {
return notFoundCounter;
}
}

View File

@ -0,0 +1,14 @@
---
weight: 0
title: VeniceDB
---
# 1. Overview
Configuration options:
- router_url: the address of the Venice Router service (default: http://localhost:7777)
- store_name: the name of the store to use (default: store1)
- token: the token to use for authentication (default: none)
# 2. Sample command
java -jar nb5/target/nb5.jar run driver=venice workload=adapter-venice/src/main/resources/venice_reader.yaml store_name=store1 router_url=http://localhost:7777 cycles=100 -v

View File

@ -0,0 +1,3 @@
router_url=http://localhost:7777
store_name=store1
token=

View File

@ -0,0 +1,13 @@
bindings:
mykey: Mod(5); ToString(); Prefix("key-")
# document level parameters that apply to all Pulsar client types:
params:
temporary_dest: "false"
blocks:
read-block:
ops:
op1:
ReadSingleKey: "store1"
key: "{mykey}"

View File

@ -31,7 +31,7 @@ public class MapLabels implements NBLabels {
parentLabels.forEach(combined::put);
childLabels.forEach((k,v) -> {
if (combined.containsKey(k))
throw new RuntimeException("Can't overlap label keys between parent and child elements. parent:" + parentLabels + ", child:" + childLabels);
throw new RuntimeException("Can't overlap label keys (for instance " + k + ") between parent and child elements. parent:" + parentLabels + ", child:" + childLabels);
combined.put(k,v);
});
labels=Collections.unmodifiableMap(combined);

View File

@ -95,6 +95,12 @@
<version>${revision}</version>
</dependency>
<dependency>
<groupId>io.nosqlbench</groupId>
<artifactId>adapter-venice</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>io.nosqlbench</groupId>
<artifactId>adapter-s4j</artifactId>

View File

@ -61,6 +61,7 @@
<module.adapter-tcp>adapter-tcp</module.adapter-tcp>
<module.adapter-dynamodb>adapter-dynamodb</module.adapter-dynamodb>
<module.adapter-mongodb>adapter-mongodb</module.adapter-mongodb>
<module.adapter-venice>adapter-venice</module.adapter-venice>
<module.adapter-pulsar>adapter-pulsar</module.adapter-pulsar>
<module.adapter-s4j>adapter-s4j</module.adapter-s4j>
<module.adapter-kafka>adapter-kafka</module.adapter-kafka>
@ -98,6 +99,7 @@
<module>adapters-api</module>
<!-- driver modules -->
<module>adapter-venice</module>
<module>adapter-diag</module>
<module>adapter-stdout</module>
<module>adapter-cqld4</module>