This is an automated email from the ASF dual-hosted git repository.
ferenc-csaky pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/flink-connector-pulsar.git
The following commit(s) were added to refs/heads/main by this push:
new 3e0a964 [FLINK-40676] Support Flink 2.0 and Pulsar Client 4.0.9
3e0a964 is described below
commit 3e0a9641ce4fd81076b274fb6e659a5734332f45
Author: fengyubiao <[email protected]>
AuthorDate: Wed Sep 16 01:32:30 2026 +0800
[FLINK-40676] Support Flink 2.0 and Pulsar Client 4.0.9
---
.github/workflows/push_pr.yml | 4 +-
.github/workflows/weekly.yml | 10 +-
flink-connector-pulsar-e2e-tests/pom.xml | 6 +-
.../tests/util/pulsar/PulsarSourceE2ECase.java | 36 +++
flink-connector-pulsar/pom.xml | 31 ++-
.../pulsar/common/config/PulsarConfiguration.java | 4 +-
.../common/schema/PulsarSchemaTypeInformation.java | 4 +-
.../common/schema/PulsarSchemaTypeSerializer.java | 2 +-
.../pulsar/common/utils/PulsarSerdeUtils.java | 47 ++++
.../flink/connector/pulsar/sink/PulsarSink.java | 17 +-
.../pulsar/sink/committer/PulsarCommitter.java | 4 +-
.../pulsar/sink/config/SinkConfiguration.java | 1 -
.../connector/pulsar/sink/writer/PulsarWriter.java | 8 +-
.../sink/writer/context/PulsarSinkContextImpl.java | 8 +-
.../pulsar/sink/writer/topic/MetadataListener.java | 5 +-
.../source/enumerator/cursor/CursorPosition.java | 25 ++
.../subscriber/impl/BasePulsarSubscriber.java | 3 +-
.../source/reader/PulsarPartitionSplitReader.java | 79 +++++-
.../source/reader/PulsarSourceFetcherManager.java | 9 +-
.../pulsar/source/reader/PulsarSourceReader.java | 28 ++-
.../PulsarDeserializationSchemaWrapper.java | 22 +-
.../reader/deserializer/PulsarSchemaWrapper.java | 19 +-
.../deserializer/PulsarTypeInformationWrapper.java | 28 ++-
.../PulsarTableSerializationSchemaFactory.java | 5 +-
.../PulsarTableDeserializationSchemaFactory.java | 5 +-
.../pulsar/common/MiniClusterTestEnvironment.java | 6 +-
.../schema/PulsarSchemaTypeInformationTest.java | 2 +-
.../schema/factories/AvroSchemaFactoryTest.java | 2 +-
.../pulsar/sink/writer/PulsarWriterTest.java | 40 +--
.../sink/writer/topic/ProducerRegisterTest.java | 10 +-
.../pulsar/source/PulsarSourceITCase.java | 37 +++
.../reader/PulsarPartitionSplitReaderTest.java | 22 +-
.../source/reader/PulsarSourceReaderTest.java | 84 ++++---
.../connector/pulsar/table/PulsarTableITCase.java | 2 +-
.../pulsar/table/PulsarTableTestBase.java | 24 +-
.../testutils/SimpleCollectIteratorAssert.java | 279 +++++++++++++++++++++
.../pulsar/testutils/function/ControlSource.java | 2 +-
.../runtime/container/PulsarContainerRuntime.java | 2 +-
flink-sql-connector-pulsar/pom.xml | 11 +-
.../src/main/resources/META-INF/NOTICE | 19 +-
pom.xml | 46 +++-
41 files changed, 828 insertions(+), 170 deletions(-)
diff --git a/.github/workflows/push_pr.yml b/.github/workflows/push_pr.yml
index 8905155..55d5bf6 100644
--- a/.github/workflows/push_pr.yml
+++ b/.github/workflows/push_pr.yml
@@ -28,8 +28,8 @@ jobs:
compile_and_test:
strategy:
matrix:
- flink: [ 1.20.4 ]
- jdk: [ '8, 11, 17' ]
+ flink: [ 2.0.2 ]
+ jdk: [ '11, 17' ]
uses: apache/flink-connector-shared-utils/.github/workflows/ci.yml@ci_utils
with:
flink_version: ${{ matrix.flink }}
diff --git a/.github/workflows/weekly.yml b/.github/workflows/weekly.yml
index 4f54b40..75cc359 100644
--- a/.github/workflows/weekly.yml
+++ b/.github/workflows/weekly.yml
@@ -31,18 +31,20 @@ jobs:
strategy:
matrix:
flink_branches: [{
- flink: 1.20-SNAPSHOT,
- branch: main
+ flink: 2.0.2,
+ branch: main,
+ jdk: "11,17"
}, {
flink: 1.20.4,
- branch: v4.2
+ branch: v4.2,
+ jdk: "8,11,17"
}
]
uses: apache/flink-connector-shared-utils/.github/workflows/ci.yml@ci_utils
with:
flink_version: ${{ matrix.flink_branches.flink }}
connector_branch: ${{ matrix.flink_branches.branch }}
- jdk_version: ${{ matrix.flink_branches.jdk || '8, 11, 17' }}
+ jdk_version: ${{ matrix.flink_branches.jdk }}
run_dependency_convergence: false
timeout_global: 120
timeout_test: 80
diff --git a/flink-connector-pulsar-e2e-tests/pom.xml
b/flink-connector-pulsar-e2e-tests/pom.xml
index 6e7c305..52acd3e 100644
--- a/flink-connector-pulsar-e2e-tests/pom.xml
+++ b/flink-connector-pulsar-e2e-tests/pom.xml
@@ -60,9 +60,13 @@ under the License.
</exclusion>
</exclusions>
</dependency>
+ <dependency>
+ <groupId>org.apache.flink</groupId>
+ <artifactId>flink-test-utils</artifactId>
+ </dependency>
<dependency>
<groupId>org.testcontainers</groupId>
- <artifactId>pulsar</artifactId>
+ <artifactId>testcontainers-pulsar</artifactId>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
diff --git
a/flink-connector-pulsar-e2e-tests/src/test/java/org/apache/flink/tests/util/pulsar/PulsarSourceE2ECase.java
b/flink-connector-pulsar-e2e-tests/src/test/java/org/apache/flink/tests/util/pulsar/PulsarSourceE2ECase.java
index e3a54f0..f9a9835 100644
---
a/flink-connector-pulsar-e2e-tests/src/test/java/org/apache/flink/tests/util/pulsar/PulsarSourceE2ECase.java
+++
b/flink-connector-pulsar-e2e-tests/src/test/java/org/apache/flink/tests/util/pulsar/PulsarSourceE2ECase.java
@@ -18,6 +18,7 @@
package org.apache.flink.tests.util.pulsar;
+import org.apache.flink.connector.pulsar.testutils.SimpleCollectIteratorAssert;
import
org.apache.flink.connector.pulsar.testutils.source.cases.MultipleTopicsConsumingContext;
import
org.apache.flink.connector.pulsar.testutils.source.cases.PartialKeysConsumingContext;
import
org.apache.flink.connector.testframe.container.FlinkContainerTestEnvironment;
@@ -31,6 +32,11 @@ import
org.apache.flink.connector.testframe.testsuites.SourceTestSuiteBase;
import org.apache.flink.core.execution.CheckpointingMode;
import org.apache.flink.tests.util.pulsar.common.FlinkContainerUtils;
import
org.apache.flink.tests.util.pulsar.common.PulsarContainerTestEnvironment;
+import org.apache.flink.util.CloseableIterator;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
import static org.apache.flink.core.execution.CheckpointingMode.EXACTLY_ONCE;
@@ -72,4 +78,34 @@ public class PulsarSourceE2ECase extends
SourceTestSuiteBase<String> {
context.addConnectorJarPaths(FlinkContainerUtils.connectorJarPaths());
return context;
};
+
+ /**
+ * {@link CollectIteratorAssertions} will generate a mismatch description
if the result does not
+ * match the expected value. It attempts to capture all following
messages, even though already
+ * failed, which helps engineers for troubleshooting, but draining the
following messages may
+ * lead the test to get stuck. We rewrite the method to avoid the test to
get stuck.
+ */
+ @Override
+ protected void checkResultWithSemantic(
+ CloseableIterator<String> resultIterator,
+ List<List<String>> testData,
+ org.apache.flink.core.execution.CheckpointingMode semantic,
+ Integer limit) {
+ if (limit != null) {
+ Runnable runnable =
+ () ->
+ new SimpleCollectIteratorAssert<>(resultIterator)
+ .withNumRecordsLimit(limit)
+ .matchesRecordsFromSource(testData,
semantic);
+
+ try {
+ CompletableFuture.runAsync(runnable).get(65, TimeUnit.SECONDS);
+ } catch (Exception e) {
+ throw new AssertionError("Timed out or failed while validating
source results.", e);
+ }
+ } else {
+ new SimpleCollectIteratorAssert<>(resultIterator)
+ .matchesRecordsFromSource(testData, semantic);
+ }
+ }
}
diff --git a/flink-connector-pulsar/pom.xml b/flink-connector-pulsar/pom.xml
index 850366d..be0aed2 100644
--- a/flink-connector-pulsar/pom.xml
+++ b/flink-connector-pulsar/pom.xml
@@ -95,6 +95,21 @@ under the License.
<artifactId>pulsar-client-all</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.github.ben-manes.caffeine</groupId>
+ <artifactId>caffeine</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>io.opentelemetry</groupId>
+ <artifactId>opentelemetry-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>io.opentelemetry</groupId>
+ <artifactId>opentelemetry-api-incubator</artifactId>
+ </dependency>
+
<!-- Tests -->
<dependency>
@@ -119,6 +134,12 @@ under the License.
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.flink</groupId>
+ <artifactId>flink-test-utils</artifactId>
+ <scope>test</scope>
+ </dependency>
+
<!-- Table factory testing -->
<dependency>
<groupId>org.apache.flink</groupId>
@@ -153,7 +174,7 @@ under the License.
<dependency>
<groupId>org.testcontainers</groupId>
- <artifactId>pulsar</artifactId>
+ <artifactId>testcontainers-pulsar</artifactId>
<scope>test</scope>
</dependency>
@@ -261,6 +282,14 @@ under the License.
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <!-- Avoid CI hanging indefinitely when
tests are done but forked JVM doesn't exit cleanly. -->
+
<forkedProcessExitTimeoutInSeconds>120</forkedProcessExitTimeoutInSeconds>
+ </configuration>
+ </plugin>
</plugins>
</build>
</project>
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/config/PulsarConfiguration.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/config/PulsarConfiguration.java
index 0681a3e..30dc831 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/config/PulsarConfiguration.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/config/PulsarConfiguration.java
@@ -77,7 +77,7 @@ public abstract class PulsarConfiguration extends
UnmodifiableConfiguration {
}
/** Get an option value from the given config, convert it into a new value
instance. */
- public <F, T> T get(ConfigOption<F> option, Function<F, T> convertor) {
+ public <F, T> T getAndConvert(ConfigOption<F> option, Function<F, T>
convertor) {
F value = get(option);
if (value != null) {
return convertor.apply(value);
@@ -97,7 +97,7 @@ public abstract class PulsarConfiguration extends
UnmodifiableConfiguration {
public <T, V> void useOption(
ConfigOption<T> option, Function<T, V> convertor, Consumer<V>
setter) {
if (contains(option) || option.hasDefaultValue()) {
- V value = get(option, convertor);
+ V value = getAndConvert(option, convertor);
setter.accept(value);
}
}
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/schema/PulsarSchemaTypeInformation.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/schema/PulsarSchemaTypeInformation.java
index ef616f0..3843548 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/schema/PulsarSchemaTypeInformation.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/schema/PulsarSchemaTypeInformation.java
@@ -19,7 +19,7 @@
package org.apache.flink.connector.pulsar.common.schema;
import org.apache.flink.annotation.Internal;
-import org.apache.flink.api.common.ExecutionConfig;
+import org.apache.flink.api.common.serialization.SerializerConfig;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.common.typeutils.TypeSerializer;
@@ -67,7 +67,7 @@ public class PulsarSchemaTypeInformation<T> extends
TypeInformation<T> {
}
@Override
- public TypeSerializer<T> createSerializer(ExecutionConfig config) {
+ public TypeSerializer<T> createSerializer(SerializerConfig
serializerConfig) {
return new PulsarSchemaTypeSerializer<>(schema);
}
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/schema/PulsarSchemaTypeSerializer.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/schema/PulsarSchemaTypeSerializer.java
index ef5c9f0..c94a851 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/schema/PulsarSchemaTypeSerializer.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/schema/PulsarSchemaTypeSerializer.java
@@ -202,7 +202,7 @@ public class PulsarSchemaTypeSerializer<T> extends
TypeSerializer<T> {
@Override
public TypeSerializerSchemaCompatibility<T> resolveSchemaCompatibility(
- TypeSerializer<T> newSerializer) {
+ TypeSerializerSnapshot<T> typeSerializerSnapshot) {
return TypeSerializerSchemaCompatibility.compatibleAsIs();
}
}
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/utils/PulsarSerdeUtils.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/utils/PulsarSerdeUtils.java
index ffe041b..eda5cab 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/utils/PulsarSerdeUtils.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/common/utils/PulsarSerdeUtils.java
@@ -19,6 +19,11 @@
package org.apache.flink.connector.pulsar.common.utils;
import org.apache.flink.annotation.Internal;
+import org.apache.flink.table.types.DataType;
+import org.apache.flink.table.types.FieldsDataType;
+import org.apache.flink.table.types.logical.LogicalType;
+import org.apache.flink.table.types.logical.LogicalTypeRoot;
+import org.apache.flink.table.types.logical.RowType;
import org.apache.flink.util.InstantiationUtil;
import org.apache.flink.util.Preconditions;
import org.apache.flink.util.function.BiConsumerWithException;
@@ -33,6 +38,10 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.apache.flink.util.Preconditions.checkArgument;
/** Util for serialize and deserialize. */
@Internal
@@ -158,4 +167,42 @@ public final class PulsarSerdeUtils {
}
return result;
}
+
+ /**
+ * Local replacement for Flink 1.18's DataTypeUtils.stripRowPrefix which
was removed in Flink
+ * 2.x.
+ */
+ public static DataType stripRowPrefix(DataType dataType, String prefix) {
+ checkArgument(dataType.getLogicalType().is(LogicalTypeRoot.ROW), "Row
data type expected.");
+ final RowType rowType = (RowType) dataType.getLogicalType();
+ final List<String> newFieldNames =
+ rowType.getFieldNames().stream()
+ .map(
+ name ->
+ name.startsWith(prefix)
+ ?
name.substring(prefix.length())
+ : name)
+ .collect(Collectors.toList());
+ final LogicalType newRowType = renameRowFields(rowType, newFieldNames);
+ return new FieldsDataType(
+ newRowType, dataType.getConversionClass(),
dataType.getChildren());
+ }
+
+ public static RowType renameRowFields(RowType rowType, List<String>
newFieldNames) {
+ Preconditions.checkArgument(
+ rowType.getFieldCount() == newFieldNames.size(),
+ "Row length and new names must match.");
+ final List<RowType.RowField> newFields =
+ IntStream.range(0, rowType.getFieldCount())
+ .mapToObj(
+ pos -> {
+ final RowType.RowField oldField =
rowType.getFields().get(pos);
+ return new RowType.RowField(
+ newFieldNames.get(pos),
+ oldField.getType(),
+
oldField.getDescription().orElse(null));
+ })
+ .collect(Collectors.toList());
+ return new RowType(rowType.isNullable(), newFields);
+ }
}
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/PulsarSink.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/PulsarSink.java
index 559da3a..7a6e303 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/PulsarSink.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/PulsarSink.java
@@ -21,7 +21,11 @@ package org.apache.flink.connector.pulsar.sink;
import org.apache.flink.annotation.Internal;
import org.apache.flink.annotation.PublicEvolving;
import org.apache.flink.api.connector.sink2.Committer;
-import org.apache.flink.api.connector.sink2.TwoPhaseCommittingSink;
+import org.apache.flink.api.connector.sink2.CommitterInitContext;
+import org.apache.flink.api.connector.sink2.CommittingSinkWriter;
+import org.apache.flink.api.connector.sink2.Sink;
+import org.apache.flink.api.connector.sink2.SupportsCommitter;
+import org.apache.flink.api.connector.sink2.WriterInitContext;
import org.apache.flink.connector.base.DeliveryGuarantee;
import org.apache.flink.connector.pulsar.common.crypto.PulsarCrypto;
import org.apache.flink.connector.pulsar.sink.committer.PulsarCommittable;
@@ -42,6 +46,8 @@ import org.apache.pulsar.client.api.PulsarClientException;
import javax.annotation.Nullable;
+import java.io.IOException;
+
import static org.apache.flink.util.Preconditions.checkNotNull;
/**
@@ -81,7 +87,7 @@ import static
org.apache.flink.util.Preconditions.checkNotNull;
* @param <IN> The input type of the sink.
*/
@PublicEvolving
-public class PulsarSink<IN> implements TwoPhaseCommittingSink<IN,
PulsarCommittable> {
+public class PulsarSink<IN> implements Sink<IN>,
SupportsCommitter<PulsarCommittable> {
private static final long serialVersionUID = 4416714587951282119L;
private final SinkConfiguration sinkConfiguration;
@@ -129,7 +135,7 @@ public class PulsarSink<IN> implements
TwoPhaseCommittingSink<IN, PulsarCommitta
@Internal
@Override
- public PrecommittingSinkWriter<IN, PulsarCommittable>
createWriter(InitContext initContext)
+ public CommittingSinkWriter<IN, PulsarCommittable>
createWriter(WriterInitContext initContext)
throws PulsarClientException {
return new PulsarWriter<>(
sinkConfiguration,
@@ -143,8 +149,9 @@ public class PulsarSink<IN> implements
TwoPhaseCommittingSink<IN, PulsarCommitta
@Internal
@Override
- public Committer<PulsarCommittable> createCommitter() {
- return new PulsarCommitter(sinkConfiguration);
+ public Committer<PulsarCommittable> createCommitter(CommitterInitContext
committerInitContext)
+ throws IOException {
+ return new PulsarCommitter(sinkConfiguration, committerInitContext);
}
@Internal
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/committer/PulsarCommitter.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/committer/PulsarCommitter.java
index c51598d..4b7506c 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/committer/PulsarCommitter.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/committer/PulsarCommitter.java
@@ -20,6 +20,7 @@ package org.apache.flink.connector.pulsar.sink.committer;
import org.apache.flink.annotation.Internal;
import org.apache.flink.api.connector.sink2.Committer;
+import org.apache.flink.api.connector.sink2.CommitterInitContext;
import org.apache.flink.connector.base.DeliveryGuarantee;
import org.apache.flink.connector.pulsar.sink.PulsarSink;
import org.apache.flink.connector.pulsar.sink.config.SinkConfiguration;
@@ -60,7 +61,8 @@ public class PulsarCommitter implements
Committer<PulsarCommittable>, Closeable
private PulsarClient pulsarClient;
private TransactionCoordinatorClient coordinatorClient;
- public PulsarCommitter(SinkConfiguration sinkConfiguration) {
+ public PulsarCommitter(
+ SinkConfiguration sinkConfiguration, CommitterInitContext
committerInitContext) {
this.sinkConfiguration = checkNotNull(sinkConfiguration);
}
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/config/SinkConfiguration.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/config/SinkConfiguration.java
index 3bc7a42..c546420 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/config/SinkConfiguration.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/config/SinkConfiguration.java
@@ -19,7 +19,6 @@
package org.apache.flink.connector.pulsar.sink.config;
import org.apache.flink.annotation.PublicEvolving;
-import org.apache.flink.api.connector.sink2.Sink.InitContext;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.connector.base.DeliveryGuarantee;
import org.apache.flink.connector.pulsar.common.config.PulsarConfiguration;
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/writer/PulsarWriter.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/writer/PulsarWriter.java
index 5c93ef3..021a8f5 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/writer/PulsarWriter.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/writer/PulsarWriter.java
@@ -22,8 +22,8 @@ import org.apache.flink.annotation.Internal;
import org.apache.flink.api.common.operators.MailboxExecutor;
import org.apache.flink.api.common.operators.ProcessingTimeService;
import
org.apache.flink.api.common.serialization.SerializationSchema.InitializationContext;
-import org.apache.flink.api.connector.sink2.Sink.InitContext;
-import
org.apache.flink.api.connector.sink2.TwoPhaseCommittingSink.PrecommittingSinkWriter;
+import org.apache.flink.api.connector.sink2.CommittingSinkWriter;
+import org.apache.flink.api.connector.sink2.WriterInitContext;
import org.apache.flink.connector.base.DeliveryGuarantee;
import org.apache.flink.connector.pulsar.common.crypto.PulsarCrypto;
import org.apache.flink.connector.pulsar.sink.committer.PulsarCommittable;
@@ -67,7 +67,7 @@ import static
org.apache.flink.util.Preconditions.checkNotNull;
* @param <IN> The type of the input elements.
*/
@Internal
-public class PulsarWriter<IN> implements PrecommittingSinkWriter<IN,
PulsarCommittable> {
+public class PulsarWriter<IN> implements CommittingSinkWriter<IN,
PulsarCommittable> {
private static final Logger LOG =
LoggerFactory.getLogger(PulsarWriter.class);
private final PulsarSerializationSchema<IN> serializationSchema;
@@ -101,7 +101,7 @@ public class PulsarWriter<IN> implements
PrecommittingSinkWriter<IN, PulsarCommi
TopicRouter<IN> topicRouter,
MessageDelayer<IN> messageDelayer,
PulsarCrypto pulsarCrypto,
- InitContext initContext)
+ WriterInitContext initContext)
throws PulsarClientException {
checkNotNull(sinkConfiguration);
this.serializationSchema = checkNotNull(serializationSchema);
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/writer/context/PulsarSinkContextImpl.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/writer/context/PulsarSinkContextImpl.java
index 8c827db..b1c5c96 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/writer/context/PulsarSinkContextImpl.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/writer/context/PulsarSinkContextImpl.java
@@ -20,7 +20,7 @@ package org.apache.flink.connector.pulsar.sink.writer.context;
import org.apache.flink.annotation.Internal;
import org.apache.flink.api.common.operators.ProcessingTimeService;
-import org.apache.flink.api.connector.sink2.Sink.InitContext;
+import org.apache.flink.api.connector.sink2.WriterInitContext;
import org.apache.flink.connector.pulsar.sink.config.SinkConfiguration;
import org.apache.flink.connector.pulsar.sink.writer.topic.MetadataListener;
import org.apache.flink.connector.pulsar.source.enumerator.topic.TopicMetadata;
@@ -38,11 +38,11 @@ public class PulsarSinkContextImpl implements
PulsarSinkContext {
private final MetadataListener metadataListener;
public PulsarSinkContextImpl(
- InitContext initContext,
+ WriterInitContext initContext,
SinkConfiguration sinkConfiguration,
MetadataListener metadataListener) {
- this.parallelInstanceId = initContext.getSubtaskId();
- this.numberOfParallelSubtasks =
initContext.getNumberOfParallelSubtasks();
+ this.parallelInstanceId =
initContext.getTaskInfo().getIndexOfThisSubtask();
+ this.numberOfParallelSubtasks =
initContext.getTaskInfo().getNumberOfParallelSubtasks();
this.processingTimeService = initContext.getProcessingTimeService();
this.enableSchemaEvolution =
sinkConfiguration.isEnableSchemaEvolution();
this.metadataListener = metadataListener;
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/writer/topic/MetadataListener.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/writer/topic/MetadataListener.java
index b324efe..8b389d6 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/writer/topic/MetadataListener.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/sink/writer/topic/MetadataListener.java
@@ -112,7 +112,10 @@ public class MetadataListener implements Serializable,
Closeable {
public Optional<Integer> load(String topic)
throws ExecutionException,
InterruptedException {
PartitionedTopicMetadata metadata =
-
clientImpl.getPartitionedTopicMetadata(topic).get();
+ clientImpl
+
.getPartitionedTopicMetadata(
+ topic, true,
true)
+ .get();
return
Optional.of(metadata.partitions);
}
});
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/enumerator/cursor/CursorPosition.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/enumerator/cursor/CursorPosition.java
index 8d92ac5..cf4f84b 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/enumerator/cursor/CursorPosition.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/enumerator/cursor/CursorPosition.java
@@ -32,6 +32,8 @@ import org.apache.pulsar.client.impl.BatchMessageIdImpl;
import org.apache.pulsar.client.impl.ChunkMessageIdImpl;
import org.apache.pulsar.client.impl.MessageIdImpl;
import org.apache.pulsar.client.impl.schema.AutoConsumeSchema;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.Serializable;
@@ -43,6 +45,7 @@ import static
org.apache.flink.util.Preconditions.checkNotNull;
@PublicEvolving
public final class CursorPosition implements Serializable {
private static final long serialVersionUID = -802405183307684549L;
+ private static final Logger LOG =
LoggerFactory.getLogger(CursorPosition.class);
private final Type type;
@@ -91,11 +94,33 @@ public final class CursorPosition implements Serializable {
.subscribe()) {
// Reset cursor to desired position.
if (type == Type.TIMESTAMP) {
+ LOG.info(
+ "[{}] [{}] reset cursor to timestamp {}",
+ topicName,
+ subscriptionName,
+ this.timestamp);
consumer.seek(getActualTimestamp(this.timestamp));
} else if (messageId instanceof ChunkMessageIdImpl) {
MessageIdAdv msgId = ((ChunkMessageIdImpl)
messageId).getFirstChunkMessageId();
+ LOG.info(
+ "[{}] [{}] reset cursor to chunk msg id {}:{}:{}/{}",
+ topicName,
+ subscriptionName,
+ msgId.getLedgerId(),
+ msgId.getEntryId(),
+ msgId.getBatchIndex(),
+ msgId.getBatchSize());
consumer.seek(getActualMessageId(msgId));
} else {
+ MessageIdAdv msgId = (MessageIdAdv) messageId;
+ LOG.info(
+ "[{}] [{}] reset cursor to msg id {}:{}:{}/{}",
+ topicName,
+ subscriptionName,
+ msgId.getLedgerId(),
+ msgId.getEntryId(),
+ msgId.getBatchIndex(),
+ msgId.getBatchSize());
consumer.seek(getActualMessageId((MessageIdAdv) messageId));
}
}
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/enumerator/subscriber/impl/BasePulsarSubscriber.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/enumerator/subscriber/impl/BasePulsarSubscriber.java
index 30a24df..5d6c443 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/enumerator/subscriber/impl/BasePulsarSubscriber.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/enumerator/subscriber/impl/BasePulsarSubscriber.java
@@ -53,7 +53,8 @@ public abstract class BasePulsarSubscriber implements
PulsarSubscriber {
}
PulsarClientImpl clientImpl = (PulsarClientImpl) client;
- PartitionedTopicMetadata metadata =
clientImpl.getPartitionedTopicMetadata(topic).get();
+ PartitionedTopicMetadata metadata =
+ clientImpl.getPartitionedTopicMetadata(topic, true,
true).get();
if (metadata.partitions == NON_PARTITIONED) {
NON_PARTITIONED_TOPICS.add(topic);
}
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/PulsarPartitionSplitReader.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/PulsarPartitionSplitReader.java
index 93d5d95..19ea784 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/PulsarPartitionSplitReader.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/PulsarPartitionSplitReader.java
@@ -46,6 +46,7 @@ import org.apache.pulsar.client.api.KeySharedPolicy;
import org.apache.pulsar.client.api.Message;
import org.apache.pulsar.client.api.MessageCrypto;
import org.apache.pulsar.client.api.MessageId;
+import org.apache.pulsar.client.api.MessageIdAdv;
import org.apache.pulsar.client.api.PulsarClient;
import org.apache.pulsar.client.api.PulsarClientException;
import org.apache.pulsar.client.api.Schema;
@@ -57,8 +58,10 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Collection;
+import java.util.Comparator;
import java.util.List;
import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -91,6 +94,27 @@ import static
org.apache.pulsar.client.api.KeySharedPolicy.stickyHashRange;
public class PulsarPartitionSplitReader
implements SplitReader<Message<byte[]>, PulsarPartitionSplit> {
private static final Logger LOG =
LoggerFactory.getLogger(PulsarPartitionSplitReader.class);
+ private static final Comparator<MessageIdAdv> MESSAGE_ID_COMPARATOR =
+ (messageId1, messageId2) -> {
+ int ledgerComparison =
+ Long.compare(messageId1.getLedgerId(),
messageId2.getLedgerId());
+ if (ledgerComparison != 0) {
+ return ledgerComparison;
+ }
+
+ int entryComparison =
+ Long.compare(messageId1.getEntryId(),
messageId2.getEntryId());
+ if (entryComparison != 0) {
+ return entryComparison;
+ }
+
+ if (messageId1 instanceof BatchMessageIdImpl
+ && messageId2 instanceof BatchMessageIdImpl) {
+ return Integer.compare(messageId1.getBatchIndex(),
messageId2.getBatchIndex());
+ }
+
+ return 0;
+ };
private final PulsarClient pulsarClient;
private final SourceConfiguration sourceConfiguration;
@@ -129,25 +153,66 @@ public class PulsarPartitionSplitReader
Deadline deadline =
Deadline.fromNow(sourceConfiguration.getMaxFetchTime());
// Consume messages from pulsar until it was woken up by flink reader.
+ CompletableFuture<Message<byte[]>> msgFuture = null;
+ MessageIdAdv latestMessageIdInTheCurrentFetch = null;
for (int messageNum = 0;
- messageNum < sourceConfiguration.getMaxFetchRecords() &&
deadline.hasTimeLeft();
- messageNum++) {
+ messageNum < sourceConfiguration.getMaxFetchRecords() &&
deadline.hasTimeLeft(); ) {
try {
int fetchTime = sourceConfiguration.getFetchOneMessageTime();
if (fetchTime <= 0) {
fetchTime = (int) deadline.timeLeftIfAny().toMillis();
}
-
- Message<byte[]> message = pulsarConsumer.receive(fetchTime,
TimeUnit.MILLISECONDS);
+ // (Highlight) The synchronised API "receive(Duration)" has a
bug, which may throw
+ // an error: "Try to
+ // reserve/release memory failed, the param memorySize is a
negative value".
+ // Here we use an asynchronous API.
+ msgFuture = pulsarConsumer.receiveAsync();
+ Message<byte[]> message = null;
+ try {
+ message = msgFuture.get(fetchTime, TimeUnit.MILLISECONDS);
+ } catch (TimeoutException e) {
+ if (msgFuture.completeExceptionally(e)) {
+ throw e;
+ } else if (!msgFuture.isCompletedExceptionally()) {
+ message = msgFuture.get();
+ } else {
+ // throws error.
+ msgFuture.get();
+ }
+ }
if (message == null) {
break;
}
+ MessageIdAdv msgId = (MessageIdAdv) message.getMessageId();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "[{}] [{}] received a message {}:{}:{}/{}.",
+ pulsarConsumer.getTopic(),
+ pulsarConsumer.getSubscription(),
+ msgId.getLedgerId(),
+ msgId.getEntryId(),
+ msgId.getBatchIndex(),
+ msgId.getBatchSize());
+ }
+ // (Highlight) Since the connector will not acknowledge
messages immediately, when
+ // the pulsar consumer
+ // reconnects, it may receive repeated messages. We use the
following two mechanism
+ // to solve the
+ // repeated receiving messages issue.
+ if (isAtOrAfter(latestMessageIdInTheCurrentFetch, msgId)
+ || isAtOrAfter(
+ (MessageIdAdv)
registeredSplit.getLatestConsumedId(), msgId)) {
+ continue;
+ }
+ latestMessageIdInTheCurrentFetch = msgId;
+
StopCondition condition = stopCursor.shouldStop(message);
if (condition == StopCondition.CONTINUE || condition ==
StopCondition.EXACTLY) {
// Collect original message.
builder.add(splitId, message);
+ messageNum++;
LOG.debug("Finished polling message {}", message);
}
@@ -165,6 +230,12 @@ public class PulsarPartitionSplitReader
return builder.build();
}
+ /** Returns whether the previous message ID is at or after the given
message ID. */
+ private static boolean isAtOrAfter(MessageIdAdv previousMessageId,
MessageIdAdv messageId) {
+ return previousMessageId != null
+ && MESSAGE_ID_COMPARATOR.compare(previousMessageId, messageId)
>= 0;
+ }
+
@Override
public void handleSplitsChanges(SplitsChange<PulsarPartitionSplit>
splitsChanges) {
LOG.debug("Handle split changes {}", splitsChanges);
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/PulsarSourceFetcherManager.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/PulsarSourceFetcherManager.java
index 2680ba7..1430d13 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/PulsarSourceFetcherManager.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/PulsarSourceFetcherManager.java
@@ -20,12 +20,9 @@ package org.apache.flink.connector.pulsar.source.reader;
import org.apache.flink.annotation.Internal;
import org.apache.flink.configuration.Configuration;
-import org.apache.flink.connector.base.source.reader.RecordsWithSplitIds;
-import org.apache.flink.connector.base.source.reader.SourceReaderBase;
import org.apache.flink.connector.base.source.reader.fetcher.SplitFetcher;
import
org.apache.flink.connector.base.source.reader.fetcher.SplitFetcherManager;
import org.apache.flink.connector.base.source.reader.splitreader.SplitReader;
-import
org.apache.flink.connector.base.source.reader.synchronization.FutureCompletingBlockingQueue;
import
org.apache.flink.connector.pulsar.source.enumerator.topic.TopicPartition;
import org.apache.flink.connector.pulsar.source.split.PulsarPartitionSplit;
@@ -59,16 +56,12 @@ public class PulsarSourceFetcherManager
/**
* Creates a new SplitFetcherManager with multiple I/O threads.
*
- * @param elementsQueue The queue that is used to hand over data from the
I/O thread (the
- * fetchers) to the reader, which emits the records and book-keeps the
state. This must be
- * the same queue instance that is also passed to the {@link
SourceReaderBase}.
* @param splitReaderSupplier The factory for the split reader that
connects to the source
*/
public PulsarSourceFetcherManager(
-
FutureCompletingBlockingQueue<RecordsWithSplitIds<Message<byte[]>>>
elementsQueue,
Supplier<SplitReader<Message<byte[]>, PulsarPartitionSplit>>
splitReaderSupplier,
Configuration configuration) {
- super(elementsQueue, splitReaderSupplier, configuration);
+ super(splitReaderSupplier, configuration);
}
/**
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/PulsarSourceReader.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/PulsarSourceReader.java
index 014d303..7c7c336 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/PulsarSourceReader.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/PulsarSourceReader.java
@@ -22,10 +22,8 @@ import org.apache.flink.annotation.Internal;
import org.apache.flink.annotation.VisibleForTesting;
import org.apache.flink.api.connector.source.ReaderOutput;
import org.apache.flink.api.connector.source.SourceReaderContext;
-import org.apache.flink.connector.base.source.reader.RecordsWithSplitIds;
import org.apache.flink.connector.base.source.reader.SourceReaderBase;
import org.apache.flink.connector.base.source.reader.splitreader.SplitReader;
-import
org.apache.flink.connector.base.source.reader.synchronization.FutureCompletingBlockingQueue;
import org.apache.flink.connector.pulsar.common.crypto.PulsarCrypto;
import org.apache.flink.connector.pulsar.common.schema.BytesSchema;
import org.apache.flink.connector.pulsar.common.schema.PulsarSchema;
@@ -41,6 +39,7 @@ import org.apache.flink.util.FlinkRuntimeException;
import org.apache.pulsar.client.api.Message;
import org.apache.pulsar.client.api.MessageId;
+import org.apache.pulsar.client.api.MessageIdAdv;
import org.apache.pulsar.client.api.PulsarClient;
import org.apache.pulsar.client.api.Schema;
import org.slf4j.Logger;
@@ -84,14 +83,12 @@ public class PulsarSourceReader<OUT>
private ScheduledExecutorService cursorScheduler;
private PulsarSourceReader(
-
FutureCompletingBlockingQueue<RecordsWithSplitIds<Message<byte[]>>>
elementsQueue,
PulsarSourceFetcherManager fetcherManager,
PulsarDeserializationSchema<OUT> deserializationSchema,
SourceConfiguration sourceConfiguration,
PulsarClient pulsarClient,
SourceReaderContext context) {
super(
- elementsQueue,
fetcherManager,
new PulsarRecordEmitter<>(deserializationSchema),
sourceConfiguration,
@@ -179,7 +176,22 @@ public class PulsarSourceReader<OUT>
for (PulsarPartitionSplit split : splits) {
MessageId latestConsumedId = split.getLatestConsumedId();
if (latestConsumedId != null) {
+ MessageIdAdv msgId = (MessageIdAdv) latestConsumedId;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "[{}] [{}] snapshot state for partition
{}:{}:{}/{}",
+ split.getPartition().getFullTopicName(),
+ sourceConfiguration.getSubscriptionName(),
+ msgId.getLedgerId(),
+ msgId.getEntryId(),
+ msgId.getBatchIndex(),
+ msgId.getBatchSize());
+ }
cursors.put(split.getPartition(), latestConsumedId);
+ } else {
+ LOG.warn(
+ "{} snapshot state for partition null",
+ split.getPartition().getFullTopicName());
}
}
// Put cursors of all the finished splits.
@@ -252,11 +264,6 @@ public class PulsarSourceReader<OUT>
SourceReaderContext readerContext)
throws Exception {
- // Create a message queue with the predefined source option.
- int queueCapacity = sourceConfiguration.getMessageQueueCapacity();
- FutureCompletingBlockingQueue<RecordsWithSplitIds<Message<byte[]>>>
elementsQueue =
- new FutureCompletingBlockingQueue<>(queueCapacity);
-
PulsarClient pulsarClient = createClient(sourceConfiguration);
// Initialize the deserialization schema before creating the pulsar
reader.
@@ -287,10 +294,9 @@ public class PulsarSourceReader<OUT>
PulsarSourceFetcherManager fetcherManager =
new PulsarSourceFetcherManager(
- elementsQueue, splitReaderSupplier,
readerContext.getConfiguration());
+ splitReaderSupplier, readerContext.getConfiguration());
return new PulsarSourceReader<>(
- elementsQueue,
fetcherManager,
deserializationSchema,
sourceConfiguration,
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/deserializer/PulsarDeserializationSchemaWrapper.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/deserializer/PulsarDeserializationSchemaWrapper.java
index ca9b11f..365e177 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/deserializer/PulsarDeserializationSchemaWrapper.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/deserializer/PulsarDeserializationSchemaWrapper.java
@@ -25,6 +25,10 @@ import
org.apache.flink.connector.pulsar.source.config.SourceConfiguration;
import org.apache.flink.util.Collector;
import org.apache.pulsar.client.api.Message;
+import org.apache.pulsar.client.api.MessageId;
+import org.apache.pulsar.client.api.MessageIdAdv;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* A {@link PulsarDeserializationSchema} implementation which based on the
given flink's {@link
@@ -36,6 +40,8 @@ import org.apache.pulsar.client.api.Message;
@Internal
public class PulsarDeserializationSchemaWrapper<T> implements
PulsarDeserializationSchema<T> {
private static final long serialVersionUID = -630646912412751300L;
+ private static final Logger LOG =
+ LoggerFactory.getLogger(PulsarDeserializationSchemaWrapper.class);
private final DeserializationSchema<T> deserializationSchema;
@@ -52,9 +58,23 @@ public class PulsarDeserializationSchemaWrapper<T>
implements PulsarDeserializat
@Override
public void deserialize(Message<byte[]> message, Collector<T> out) throws
Exception {
+ MessageId msgId = message.getMessageId();
+ MessageIdAdv messageIdAdv = (MessageIdAdv) msgId;
byte[] bytes = message.getData();
T instance = deserializationSchema.deserialize(bytes);
-
+ if (LOG.isDebugEnabled()) {
+ if (messageIdAdv != null) {
+ LOG.debug(
+ "Deserialize message {}:{}:{}/{} of {}",
+ messageIdAdv.getLedgerId(),
+ messageIdAdv.getEntryId(),
+ messageIdAdv.getBatchIndex(),
+ messageIdAdv.getBatchSize(),
+ String.valueOf(instance));
+ } else {
+ LOG.debug("Deserialize message {id-null} of {}",
String.valueOf(instance));
+ }
+ }
out.collect(instance);
}
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/deserializer/PulsarSchemaWrapper.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/deserializer/PulsarSchemaWrapper.java
index 37553a5..26954e3 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/deserializer/PulsarSchemaWrapper.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/deserializer/PulsarSchemaWrapper.java
@@ -23,9 +23,12 @@ import
org.apache.flink.connector.pulsar.common.schema.PulsarSchema;
import org.apache.flink.util.Collector;
import org.apache.pulsar.client.api.Message;
+import org.apache.pulsar.client.api.MessageIdAdv;
import org.apache.pulsar.client.api.Schema;
import org.apache.pulsar.common.schema.KeyValue;
import org.apache.pulsar.common.schema.SchemaInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import static
org.apache.flink.connector.pulsar.common.schema.PulsarSchemaUtils.createTypeInformation;
@@ -38,6 +41,7 @@ import static
org.apache.flink.connector.pulsar.common.schema.PulsarSchemaUtils.
@Internal
public class PulsarSchemaWrapper<T> implements PulsarDeserializationSchema<T> {
private static final long serialVersionUID = -4864701207257059158L;
+ private static final Logger LOG =
LoggerFactory.getLogger(PulsarSchemaWrapper.class);
/** The serializable pulsar schema, it wrap the schema with type class. */
private final PulsarSchema<T> pulsarSchema;
@@ -64,7 +68,20 @@ public class PulsarSchemaWrapper<T> implements
PulsarDeserializationSchema<T> {
Schema<T> schema = this.pulsarSchema.getPulsarSchema();
byte[] bytes = message.getData();
T instance = schema.decode(bytes);
-
+ MessageIdAdv messageIdAdv = (MessageIdAdv) message.getMessageId();
+ if (LOG.isDebugEnabled()) {
+ if (messageIdAdv != null) {
+ LOG.debug(
+ "Deserialize message {}:{}:{}/{} of {}",
+ messageIdAdv.getLedgerId(),
+ messageIdAdv.getEntryId(),
+ messageIdAdv.getBatchIndex(),
+ messageIdAdv.getBatchSize(),
+ String.valueOf(instance));
+ } else {
+ LOG.debug("Deserialize message {id-null} of {}",
String.valueOf(instance));
+ }
+ }
out.collect(instance);
}
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/deserializer/PulsarTypeInformationWrapper.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/deserializer/PulsarTypeInformationWrapper.java
index 59f77d7..4bfdd19 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/deserializer/PulsarTypeInformationWrapper.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/source/reader/deserializer/PulsarTypeInformationWrapper.java
@@ -21,11 +21,15 @@ import org.apache.flink.annotation.Internal;
import org.apache.flink.api.common.ExecutionConfig;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.common.typeutils.TypeSerializer;
-import org.apache.flink.api.java.ExecutionEnvironment;
import org.apache.flink.core.memory.DataInputDeserializer;
import org.apache.flink.util.Collector;
import org.apache.pulsar.client.api.Message;
+import org.apache.pulsar.client.api.MessageIdAdv;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
/**
* Wrap the flink TypeInformation into a {@code PulsarDeserializationSchema}.
We would create a
@@ -35,6 +39,7 @@ import org.apache.pulsar.client.api.Message;
@Internal
public class PulsarTypeInformationWrapper<T> implements
PulsarDeserializationSchema<T> {
private static final long serialVersionUID = 6647084180084963022L;
+ private static final Logger LOG =
LoggerFactory.getLogger(PulsarTypeInformationWrapper.class);
/**
* PulsarDeserializationSchema would be shared for multiple SplitReaders
in different fetcher
@@ -47,9 +52,11 @@ public class PulsarTypeInformationWrapper<T> implements
PulsarDeserializationSch
private final TypeInformation<T> information;
private final TypeSerializer<T> serializer;
- public PulsarTypeInformationWrapper(TypeInformation<T> information,
ExecutionConfig config) {
+ public PulsarTypeInformationWrapper(
+ TypeInformation<T> information, @Nullable ExecutionConfig config) {
this.information = information;
- this.serializer = information.createSerializer(config);
+ final ExecutionConfig executionConfig = config == null ? new
ExecutionConfig() : config;
+ this.serializer =
information.createSerializer(executionConfig.getSerializerConfig());
}
@Override
@@ -57,7 +64,20 @@ public class PulsarTypeInformationWrapper<T> implements
PulsarDeserializationSch
DataInputDeserializer dis = DESERIALIZER.get();
dis.setBuffer(message.getData());
T instance = serializer.deserialize(dis);
-
+ MessageIdAdv messageIdAdv = (MessageIdAdv) message.getMessageId();
+ if (LOG.isDebugEnabled()) {
+ if (messageIdAdv != null) {
+ LOG.debug(
+ "Deserialize message {}:{}:{}/{} of {}",
+ messageIdAdv.getLedgerId(),
+ messageIdAdv.getEntryId(),
+ messageIdAdv.getBatchIndex(),
+ messageIdAdv.getBatchSize(),
+ String.valueOf(instance));
+ } else {
+ LOG.debug("Deserialize message {id-null} of {}",
String.valueOf(instance));
+ }
+ }
out.collect(instance);
}
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/table/sink/PulsarTableSerializationSchemaFactory.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/table/sink/PulsarTableSerializationSchemaFactory.java
index 95c443b..cff2ca7 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/table/sink/PulsarTableSerializationSchemaFactory.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/table/sink/PulsarTableSerializationSchemaFactory.java
@@ -15,6 +15,7 @@
package org.apache.flink.connector.pulsar.table.sink;
import org.apache.flink.api.common.serialization.SerializationSchema;
+import org.apache.flink.connector.pulsar.common.utils.PulsarSerdeUtils;
import
org.apache.flink.connector.pulsar.sink.writer.serializer.PulsarSerializationSchema;
import org.apache.flink.table.connector.Projection;
import org.apache.flink.table.connector.format.EncodingFormat;
@@ -22,7 +23,6 @@ import org.apache.flink.table.connector.sink.DynamicTableSink;
import org.apache.flink.table.data.RowData;
import org.apache.flink.table.types.DataType;
import org.apache.flink.table.types.logical.LogicalType;
-import org.apache.flink.table.types.utils.DataTypeUtils;
import javax.annotation.Nullable;
@@ -107,7 +107,8 @@ public class PulsarTableSerializationSchemaFactory {
}
DataType physicalFormatDataType =
Projection.of(projection).project(this.physicalDataType);
if (prefix != null) {
- physicalFormatDataType =
DataTypeUtils.stripRowPrefix(physicalFormatDataType, prefix);
+ physicalFormatDataType =
+ PulsarSerdeUtils.stripRowPrefix(physicalFormatDataType,
prefix);
}
return format.createRuntimeEncoder(context, physicalFormatDataType);
}
diff --git
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/table/source/PulsarTableDeserializationSchemaFactory.java
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/table/source/PulsarTableDeserializationSchemaFactory.java
index 32294b8..91515a8 100644
---
a/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/table/source/PulsarTableDeserializationSchemaFactory.java
+++
b/flink-connector-pulsar/src/main/java/org/apache/flink/connector/pulsar/table/source/PulsarTableDeserializationSchemaFactory.java
@@ -20,6 +20,7 @@ package org.apache.flink.connector.pulsar.table.source;
import org.apache.flink.api.common.serialization.DeserializationSchema;
import org.apache.flink.api.common.typeinfo.TypeInformation;
+import org.apache.flink.connector.pulsar.common.utils.PulsarSerdeUtils;
import
org.apache.flink.connector.pulsar.source.reader.deserializer.PulsarDeserializationSchema;
import org.apache.flink.table.connector.Projection;
import org.apache.flink.table.connector.format.DecodingFormat;
@@ -27,7 +28,6 @@ import
org.apache.flink.table.connector.source.DynamicTableSource;
import org.apache.flink.table.connector.source.ScanTableSource;
import org.apache.flink.table.data.RowData;
import org.apache.flink.table.types.DataType;
-import org.apache.flink.table.types.utils.DataTypeUtils;
import javax.annotation.Nullable;
@@ -117,7 +117,8 @@ public class PulsarTableDeserializationSchemaFactory
implements Serializable {
DataType physicalFormatDataType =
Projection.of(projection).project(this.physicalDataType);
if (prefix != null) {
- physicalFormatDataType =
DataTypeUtils.stripRowPrefix(physicalFormatDataType, prefix);
+ physicalFormatDataType =
+ PulsarSerdeUtils.stripRowPrefix(physicalFormatDataType,
prefix);
}
return format.createRuntimeDecoder(context, physicalFormatDataType);
}
diff --git
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/common/MiniClusterTestEnvironment.java
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/common/MiniClusterTestEnvironment.java
index 83a7f36..af980fd 100644
---
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/common/MiniClusterTestEnvironment.java
+++
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/common/MiniClusterTestEnvironment.java
@@ -25,6 +25,7 @@ import
org.apache.flink.connector.testframe.environment.TestEnvironment;
import
org.apache.flink.connector.testframe.environment.TestEnvironmentSettings;
import org.apache.flink.core.execution.JobClient;
import
org.apache.flink.runtime.highavailability.nonha.embedded.HaLeadershipControl;
+import org.apache.flink.runtime.jobgraph.SavepointRestoreSettings;
import org.apache.flink.runtime.minicluster.RpcServiceSharing;
import org.apache.flink.runtime.taskexecutor.TaskExecutorResourceUtils;
import org.apache.flink.runtime.testutils.CommonTestUtils;
@@ -49,7 +50,6 @@ import java.util.stream.Collectors;
import static
org.apache.flink.configuration.MetricOptions.METRIC_FETCHER_UPDATE_INTERVAL;
import static
org.apache.flink.connector.testframe.utils.ConnectorTestConstants.METRIC_FETCHER_UPDATE_INTERVAL_MS;
-import static
org.apache.flink.runtime.jobgraph.SavepointConfigOptions.SAVEPOINT_PATH;
/** Test environment for running jobs on Flink mini-cluster. */
@Experimental
@@ -91,7 +91,9 @@ public class MiniClusterTestEnvironment implements
TestEnvironment, ClusterContr
TestEnvironmentSettings envOptions) {
Configuration configuration = new Configuration();
if (envOptions.getSavepointRestorePath() != null) {
- configuration.setString(SAVEPOINT_PATH,
envOptions.getSavepointRestorePath());
+ SavepointRestoreSettings.toConfiguration(
+
SavepointRestoreSettings.forPath(envOptions.getSavepointRestorePath()),
+ configuration);
}
return new TestStreamEnvironment(
this.miniCluster.getMiniCluster(),
diff --git
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/common/schema/PulsarSchemaTypeInformationTest.java
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/common/schema/PulsarSchemaTypeInformationTest.java
index 2f56f90..853d385 100644
---
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/common/schema/PulsarSchemaTypeInformationTest.java
+++
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/common/schema/PulsarSchemaTypeInformationTest.java
@@ -40,7 +40,7 @@ class PulsarSchemaTypeInformationTest {
PulsarSchemaTypeInformation<Bar> clonedInfo =
InstantiationUtil.clone(info);
assertThat(clonedInfo).isEqualTo(info).isNotSameAs(info);
- assertThatCode(() -> info.createSerializer(new ExecutionConfig()))
+ assertThatCode(() -> info.createSerializer(new
ExecutionConfig().getSerializerConfig()))
.doesNotThrowAnyException();
assertThat(clonedInfo.getTypeClass()).isEqualTo(info.getTypeClass());
diff --git
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/common/schema/factories/AvroSchemaFactoryTest.java
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/common/schema/factories/AvroSchemaFactoryTest.java
index 14d907d..0729bcf 100644
---
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/common/schema/factories/AvroSchemaFactoryTest.java
+++
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/common/schema/factories/AvroSchemaFactoryTest.java
@@ -91,7 +91,7 @@ class AvroSchemaFactoryTest {
// Serialize by type information.
TypeSerializer<StructWithAnnotations> serializer =
- information.createSerializer(new ExecutionConfig());
+ information.createSerializer(new
ExecutionConfig().getSerializerConfig());
// TypeInformation serialization.
assertThatCode(() ->
InstantiationUtil.clone(information)).doesNotThrowAnyException();
assertThatCode(() ->
InstantiationUtil.clone(serializer)).doesNotThrowAnyException();
diff --git
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/sink/writer/PulsarWriterTest.java
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/sink/writer/PulsarWriterTest.java
index d24f230..31ffd1b 100644
---
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/sink/writer/PulsarWriterTest.java
+++
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/sink/writer/PulsarWriterTest.java
@@ -20,13 +20,15 @@ package org.apache.flink.connector.pulsar.sink.writer;
import org.apache.flink.api.common.JobID;
import org.apache.flink.api.common.JobInfo;
+import org.apache.flink.api.common.JobInfoImpl;
import org.apache.flink.api.common.TaskInfo;
+import org.apache.flink.api.common.TaskInfoImpl;
import org.apache.flink.api.common.operators.MailboxExecutor;
import org.apache.flink.api.common.operators.ProcessingTimeService;
import org.apache.flink.api.common.serialization.SerializationSchema;
import org.apache.flink.api.common.typeutils.TypeSerializer;
-import org.apache.flink.api.connector.sink2.Sink.InitContext;
import org.apache.flink.api.connector.sink2.SinkWriter;
+import org.apache.flink.api.connector.sink2.WriterInitContext;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.connector.base.DeliveryGuarantee;
import org.apache.flink.connector.pulsar.common.crypto.PulsarCrypto;
@@ -162,12 +164,14 @@ class PulsarWriterTest extends PulsarTestSuiteBase {
}
}
- private static class MockInitContext implements InitContext {
+ private static class MockInitContext implements WriterInitContext {
private final MetricListener metricListener;
private final OperatorIOMetricGroup ioMetricGroup;
private final SinkWriterMetricGroup metricGroup;
private final ProcessingTimeService timeService;
+ private final JobInfo jobInfo;
+ private final TaskInfo taskInfo;
private MockInitContext() {
this.metricListener = new MetricListener();
@@ -178,6 +182,8 @@ class PulsarWriterTest extends PulsarTestSuiteBase {
this.metricGroup =
MetricsGroupTestUtils.mockWriterMetricGroup(metricGroup,
ioMetricGroup);
this.timeService = new TestProcessingTimeService();
+ this.jobInfo = new JobInfoImpl(new JobID(), "pulsar-writer-test");
+ this.taskInfo = new TaskInfoImpl("pulsar-writer-test-task", 1, 0,
1, 0);
}
@Override
@@ -196,39 +202,15 @@ class PulsarWriterTest extends PulsarTestSuiteBase {
}
@Override
- public int getSubtaskId() {
- return 0;
- }
-
- @Override
- public int getNumberOfParallelSubtasks() {
- return 1;
- }
-
- @Override
- public int getAttemptNumber() {
- return 0;
- }
-
- // The following three methods are for compatibility with
- //
https://github.com/apache/flink/commit/4f5b2fb5736f5a1c098a7dc1d448a879f36f801b
- // . Removed the commented out `@Override` when we move to 1.18.
-
- // @Override
public boolean isObjectReuseEnabled() {
return false;
}
- // @Override
+ @Override
public <IN> TypeSerializer<IN> createInputSerializer() {
return null;
}
- // @Override
- public JobID getJobId() {
- return null;
- }
-
@Override
public SinkWriterMetricGroup metricGroup() {
return metricGroup;
@@ -257,12 +239,12 @@ class PulsarWriterTest extends PulsarTestSuiteBase {
@Override
public JobInfo getJobInfo() {
- return null;
+ return jobInfo;
}
@Override
public TaskInfo getTaskInfo() {
- return null;
+ return taskInfo;
}
}
diff --git
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/sink/writer/topic/ProducerRegisterTest.java
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/sink/writer/topic/ProducerRegisterTest.java
index 9e0dabf..03fef2b 100644
---
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/sink/writer/topic/ProducerRegisterTest.java
+++
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/sink/writer/topic/ProducerRegisterTest.java
@@ -28,9 +28,9 @@ import
org.apache.flink.connector.pulsar.testutils.PulsarTestSuiteBase;
import org.apache.pulsar.client.api.Message;
import org.apache.pulsar.client.api.Schema;
import org.apache.pulsar.client.api.SchemaSerializationException;
-import org.apache.pulsar.client.api.TypedMessageBuilder;
import org.apache.pulsar.client.api.transaction.TransactionCoordinatorClient;
import org.apache.pulsar.client.api.transaction.TxnID;
+import org.apache.pulsar.client.impl.TypedMessageBuilderImpl;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
@@ -113,9 +113,11 @@ class ProducerRegisterTest extends PulsarTestSuiteBase {
sinkConfiguration, PulsarCrypto.disabled(),
createSinkWriterMetricGroup());
long message = ThreadLocalRandom.current().nextLong();
- TypedMessageBuilder<byte[]> builder =
register.createMessageBuilder(topic, Schema.BYTES);
-
- assertThatThrownBy(() -> builder.value(Schema.INT64.encode(message)))
+ TypedMessageBuilderImpl<Object> builder =
+ (TypedMessageBuilderImpl<Object>)
+ register.createMessageBuilder(topic, Schema.BYTES);
+ builder.value(Schema.INT64.encode(message));
+ assertThatThrownBy(() -> builder.getMessage())
.isInstanceOf(SchemaSerializationException.class);
}
}
diff --git
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/source/PulsarSourceITCase.java
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/source/PulsarSourceITCase.java
index 63b2da7..8c427f8 100644
---
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/source/PulsarSourceITCase.java
+++
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/source/PulsarSourceITCase.java
@@ -21,6 +21,7 @@ package org.apache.flink.connector.pulsar.source;
import org.apache.flink.connector.pulsar.common.MiniClusterTestEnvironment;
import org.apache.flink.connector.pulsar.testutils.PulsarTestContextFactory;
import org.apache.flink.connector.pulsar.testutils.PulsarTestEnvironment;
+import org.apache.flink.connector.pulsar.testutils.SimpleCollectIteratorAssert;
import org.apache.flink.connector.pulsar.testutils.runtime.PulsarRuntime;
import
org.apache.flink.connector.pulsar.testutils.source.cases.EncryptedMessagesConsumingContext;
import
org.apache.flink.connector.pulsar.testutils.source.cases.MultipleTopicsConsumingContext;
@@ -31,10 +32,16 @@ import
org.apache.flink.connector.testframe.junit.annotations.TestEnv;
import
org.apache.flink.connector.testframe.junit.annotations.TestExternalSystem;
import org.apache.flink.connector.testframe.junit.annotations.TestSemantics;
import org.apache.flink.connector.testframe.testsuites.SourceTestSuiteBase;
+import org.apache.flink.connector.testframe.utils.CollectIteratorAssertions;
import org.apache.flink.core.execution.CheckpointingMode;
+import org.apache.flink.util.CloseableIterator;
import org.apache.pulsar.client.api.SubscriptionType;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
import static org.apache.flink.core.execution.CheckpointingMode.EXACTLY_ONCE;
/**
@@ -70,4 +77,34 @@ class PulsarSourceITCase extends SourceTestSuiteBase<String>
{
@TestContext
PulsarTestContextFactory<String, EncryptedMessagesConsumingContext>
encryptMessages =
new PulsarTestContextFactory<>(pulsar,
EncryptedMessagesConsumingContext::new);
+
+ /**
+ * {@link CollectIteratorAssertions} will generate a mismatch description
if the result does not
+ * match the expected value. It attempts to capture all following
messages, even though already
+ * failed, which helps engineers for troubleshooting, but draining the
following messages may
+ * lead the test to get stuck. We rewrite the method to avoid the test to
get stuck.
+ */
+ @Override
+ protected void checkResultWithSemantic(
+ CloseableIterator<String> resultIterator,
+ List<List<String>> expectedData,
+ org.apache.flink.core.execution.CheckpointingMode semantic,
+ Integer limit) {
+ if (limit != null) {
+ Runnable runnable =
+ () ->
+ new SimpleCollectIteratorAssert<>(resultIterator)
+ .withNumRecordsLimit(limit)
+ .matchesRecordsFromSource(expectedData,
semantic);
+
+ try {
+ CompletableFuture.runAsync(runnable).get(65, TimeUnit.SECONDS);
+ } catch (Exception e) {
+ throw new AssertionError("Timed out or failed while validating
source results.", e);
+ }
+ } else {
+ new SimpleCollectIteratorAssert<>(resultIterator)
+ .matchesRecordsFromSource(expectedData, semantic);
+ }
+ }
}
diff --git
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/source/reader/PulsarPartitionSplitReaderTest.java
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/source/reader/PulsarPartitionSplitReaderTest.java
index 4b439a0..7fae15b 100644
---
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/source/reader/PulsarPartitionSplitReaderTest.java
+++
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/source/reader/PulsarPartitionSplitReaderTest.java
@@ -72,7 +72,7 @@ class PulsarPartitionSplitReaderTest extends
PulsarTestSuiteBase {
String topicName = randomAlphabetic(10);
// Add a split
- handleSplit(splitReader, topicName, 0, MessageId.latest);
+ handleSplit(splitReader, topicName, 0, MessageId.earliest);
// Poll once with a null message
Message<byte[]> message1 = fetchedMessage(splitReader);
@@ -97,7 +97,7 @@ class PulsarPartitionSplitReaderTest extends
PulsarTestSuiteBase {
PulsarPartitionSplitReader splitReader = splitReader();
String topicName = randomAlphabetic(10);
- handleSplit(splitReader, topicName, 0, MessageId.latest);
+ handleSplit(splitReader, topicName, 0, MessageId.earliest);
operator().sendMessage(topicNameWithPartition(topicName, 0), STRING,
randomAlphabetic(10));
fetchedMessages(splitReader, 1, true);
}
@@ -263,16 +263,20 @@ class PulsarPartitionSplitReaderTest extends
PulsarTestSuiteBase {
.admin()
.topics()
.getLastMessageId(topicNameWithPartition(topicName, 0));
- // when recover, use exclusive startCursor
- handleSplit(
- splitReader,
- topicName,
- 0,
+ MessageId startMessageId =
new MessageIdImpl(
lastMessageId.getLedgerId(),
lastMessageId.getEntryId() - 1,
- lastMessageId.getPartitionIndex()));
- fetchedMessages(splitReader, 1, true);
+ lastMessageId.getPartitionIndex());
+ try {
+ // when recover, use exclusive startCursor
+ handleSplit(splitReader, topicName, 0, startMessageId);
+ fetchedMessages(splitReader, 1, true);
+ } catch (Throwable t) {
+ throw t;
+ } finally {
+ splitReader.close();
+ }
}
@Test
diff --git
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/source/reader/PulsarSourceReaderTest.java
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/source/reader/PulsarSourceReaderTest.java
index 3d4619d..eedf4b8 100644
---
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/source/reader/PulsarSourceReaderTest.java
+++
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/source/reader/PulsarSourceReaderTest.java
@@ -56,6 +56,7 @@ import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import static java.util.Collections.emptyList;
@@ -143,45 +144,56 @@ class PulsarSourceReaderTest extends PulsarTestSuiteBase {
void offsetCommitOnCheckpointComplete() throws Exception {
String topicName = topicName();
PulsarSourceReader<Integer> reader = sourceReader();
+ AtomicBoolean readerClosed = new AtomicBoolean(false);
// consume more than 1 partition
- reader.addSplits(
- createPartitionSplits(
- topicName, DEFAULT_PARTITIONS,
Boundedness.CONTINUOUS_UNBOUNDED));
- reader.notifyNoMoreSplits();
- TestingReaderOutput<Integer> output = new TestingReaderOutput<>();
- long checkpointId = 0;
- int emptyResultTime = 0;
- InputStatus status;
- do {
- checkpointId++;
- status = reader.pollNext(output);
- // Create a checkpoint for each message consumption, but not
complete them.
- reader.snapshotState(checkpointId);
- // the first couple of pollNext() might return NOTHING_AVAILABLE
before data appears
- if (InputStatus.NOTHING_AVAILABLE == status) {
- emptyResultTime++;
- sleepUninterruptibly(1, TimeUnit.SECONDS);
+ try {
+ reader.addSplits(
+ createPartitionSplits(
+ topicName, DEFAULT_PARTITIONS,
Boundedness.CONTINUOUS_UNBOUNDED));
+ reader.notifyNoMoreSplits();
+ TestingReaderOutput<Integer> output = new TestingReaderOutput<>();
+ long checkpointId = 0;
+ int emptyResultTime = 0;
+ InputStatus status;
+ do {
+ checkpointId++;
+ status = reader.pollNext(output);
+ // Create a checkpoint for each message consumption, but not
complete them.
+ reader.snapshotState(checkpointId);
+ // the first couple of pollNext() might return
NOTHING_AVAILABLE before data appears
+ if (InputStatus.NOTHING_AVAILABLE == status) {
+ emptyResultTime++;
+ sleepUninterruptibly(1, TimeUnit.SECONDS);
+ }
+
+ } while (emptyResultTime < MAX_EMPTY_POLLING_TIMES
+ && status != InputStatus.END_OF_INPUT
+ && output.getEmittedRecords().size()
+ < NUM_RECORDS_PER_PARTITION * DEFAULT_PARTITIONS);
+
+ // The completion of the last checkpoint should subsume all
previous checkpoints.
+ assertThat(reader.cursorsToCommit).hasSize((int) checkpointId);
+ long lastCheckpointId = checkpointId;
+ // notify checkpoint complete and expect all cursors committed
+ assertThatCode(() ->
reader.notifyCheckpointComplete(lastCheckpointId))
+ .doesNotThrowAnyException();
+ assertThat(reader.cursorsToCommit).isEmpty();
+
+ // Verify the committed offsets.
+ readerClosed.set(true);
+ reader.close();
+ for (int i = 0; i < DEFAULT_PARTITIONS; i++) {
+ verifyAllMessageAcknowledged(
+ NUM_RECORDS_PER_PARTITION,
+ TopicNameUtils.topicNameWithPartition(topicName, i));
+ }
+ } catch (Throwable t) {
+ throw t;
+ } finally {
+ if (!readerClosed.get()) {
+ reader.close();
}
-
- } while (emptyResultTime < MAX_EMPTY_POLLING_TIMES
- && status != InputStatus.END_OF_INPUT
- && output.getEmittedRecords().size()
- < NUM_RECORDS_PER_PARTITION * DEFAULT_PARTITIONS);
-
- // The completion of the last checkpoint should subsume all previous
checkpoints.
- assertThat(reader.cursorsToCommit).hasSize((int) checkpointId);
- long lastCheckpointId = checkpointId;
- // notify checkpoint complete and expect all cursors committed
- assertThatCode(() -> reader.notifyCheckpointComplete(lastCheckpointId))
- .doesNotThrowAnyException();
- assertThat(reader.cursorsToCommit).isEmpty();
-
- // Verify the committed offsets.
- reader.close();
- for (int i = 0; i < DEFAULT_PARTITIONS; i++) {
- verifyAllMessageAcknowledged(
- NUM_RECORDS_PER_PARTITION,
TopicNameUtils.topicNameWithPartition(topicName, i));
}
}
diff --git
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/table/PulsarTableITCase.java
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/table/PulsarTableITCase.java
index eb83967..fc0b9ea 100644
---
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/table/PulsarTableITCase.java
+++
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/table/PulsarTableITCase.java
@@ -22,7 +22,7 @@ import org.apache.flink.api.common.JobExecutionResult;
import org.apache.flink.connector.pulsar.table.testutils.TestingUser;
import org.apache.flink.core.execution.JobClient;
import org.apache.flink.streaming.api.datastream.DataStream;
-import org.apache.flink.streaming.api.functions.sink.SinkFunction;
+import org.apache.flink.streaming.api.functions.sink.legacy.SinkFunction;
import org.apache.flink.table.api.DataTypes;
import org.apache.flink.test.junit5.MiniClusterExtension;
import org.apache.flink.test.util.SuccessException;
diff --git
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/table/PulsarTableTestBase.java
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/table/PulsarTableTestBase.java
index cecd3e2..40eb78a 100644
---
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/table/PulsarTableTestBase.java
+++
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/table/PulsarTableTestBase.java
@@ -18,7 +18,8 @@
package org.apache.flink.connector.pulsar.table;
-import org.apache.flink.api.common.restartstrategy.RestartStrategies;
+import org.apache.flink.configuration.Configuration;
+import org.apache.flink.configuration.RestartStrategyOptions;
import org.apache.flink.connector.pulsar.common.MiniClusterTestEnvironment;
import org.apache.flink.connector.pulsar.testutils.PulsarTestEnvironment;
import org.apache.flink.connector.pulsar.testutils.runtime.PulsarRuntime;
@@ -32,10 +33,14 @@ import
org.apache.flink.table.api.bridge.java.StreamTableEnvironment;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.TestInstance;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/** Base class for Pulsar table integration test. */
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public abstract class PulsarTableTestBase {
+ private static final Logger LOG =
LoggerFactory.getLogger(PulsarTableTestBase.class);
+
@TestEnv protected MiniClusterTestEnvironment flink = new
MiniClusterTestEnvironment();
// Defines pulsar running environment
@@ -54,11 +59,15 @@ public abstract class PulsarTableTestBase {
@BeforeAll
public void beforeAll() throws Exception {
+ LOG.info("Starting Pulsar table test environment for {}.",
getClass().getSimpleName());
pulsar.startUp();
+ LOG.info("Pulsar test environment started for {}.",
getClass().getSimpleName());
// run env
env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(DEFAULT_PARALLELISM);
- env.getConfig().setRestartStrategy(RestartStrategies.noRestart());
+ Configuration noRestart = new Configuration();
+ noRestart.set(RestartStrategyOptions.RESTART_STRATEGY, "disable");
+ env.configure(noRestart);
tableEnv = StreamTableEnvironment.create(env);
tableEnv.getConfig()
.getConfiguration()
@@ -71,6 +80,15 @@ public abstract class PulsarTableTestBase {
@AfterAll
public void afterAll() throws Exception {
- pulsar.tearDown();
+ final long start = System.currentTimeMillis();
+ LOG.info("Tearing down Pulsar table test environment for {}.",
getClass().getSimpleName());
+ try {
+ pulsar.tearDown();
+ } finally {
+ LOG.info(
+ "Finished Pulsar table test environment teardown for {} in
{} ms.",
+ getClass().getSimpleName(),
+ System.currentTimeMillis() - start);
+ }
}
}
diff --git
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/testutils/SimpleCollectIteratorAssert.java
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/testutils/SimpleCollectIteratorAssert.java
new file mode 100644
index 0000000..13c445e
--- /dev/null
+++
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/testutils/SimpleCollectIteratorAssert.java
@@ -0,0 +1,279 @@
+/*
+ * 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.flink.connector.pulsar.testutils;
+
+import org.apache.flink.core.execution.CheckpointingMode;
+
+import org.assertj.core.api.AbstractAssert;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import static
org.apache.flink.streaming.api.CheckpointingMode.convertToCheckpointingMode;
+
+/**
+ * Difference with {@link
org.apache.flink.connector.testframe.utils.CollectIteratorAssertions}
+ * CollectIteratorAssertions will generate a mismatch description if the
result does not match the
+ * expected value. It attempts to capture all following messages, even though
already failed, which
+ * helps engineers for troubleshooting, but draining the following messages
may lead the test to get
+ * stuck.
+ *
+ * <p>The current implementation will immediately fail once a message does not
match, skips to drain
+ * the following messages to build the information that describes failure.
+ */
+public class SimpleCollectIteratorAssert<T>
+ extends AbstractAssert<SimpleCollectIteratorAssert<T>, Iterator<T>> {
+
+ private final Iterator<T> collectorIterator;
+ private final List<RecordsFromSplit<T>> expectedRecordsFromSplits = new
ArrayList<>();
+ private int totalNumRecords;
+ private Integer limit = null;
+
+ public SimpleCollectIteratorAssert(Iterator<T> collectorIterator) {
+ super(collectorIterator, SimpleCollectIteratorAssert.class);
+ this.collectorIterator = collectorIterator;
+ }
+
+ public SimpleCollectIteratorAssert<T> withNumRecordsLimit(int limit) {
+ this.limit = limit;
+ return this;
+ }
+
+ /**
+ * This method is required for downstream projects e.g. Flink connectors
extending this test for
+ * the case when there should be supported Flink versions below 1.20.
Could be removed together
+ * with dropping support for Flink 1.19.
+ */
+ @Deprecated
+ public void matchesRecordsFromSource(
+ List<List<T>> recordsBySplitsFromSource,
+ org.apache.flink.streaming.api.CheckpointingMode semantic) {
+ matchesRecordsFromSource(recordsBySplitsFromSource,
convertToCheckpointingMode(semantic));
+ }
+
+ public void matchesRecordsFromSource(List<List<T>> expectedData,
CheckpointingMode semantic) {
+ for (List<T> recordsFromSplit : expectedData) {
+ expectedRecordsFromSplits.add(new
RecordsFromSplit<>(recordsFromSplit));
+ totalNumRecords += recordsFromSplit.size();
+ }
+
+ if (limit != null && limit > totalNumRecords) {
+ throw new IllegalArgumentException(
+ "Limit validation size should be less than total number of
records from source");
+ }
+
+ switch (semantic) {
+ case AT_LEAST_ONCE:
+ compareWithAtLeastOnceSemantic(collectorIterator,
expectedRecordsFromSplits);
+ break;
+ case EXACTLY_ONCE:
+ compareWithExactlyOnceSemantic(collectorIterator,
expectedRecordsFromSplits);
+ break;
+ default:
+ throw new IllegalArgumentException(
+ String.format("Unrecognized semantic \"%s\"",
semantic));
+ }
+ }
+
+ private void compareWithAtLeastOnceSemantic(
+ Iterator<T> resultIterator, List<RecordsFromSplit<T>>
recordsFromSplits) {
+ List<T> duplicateRead = new LinkedList<>();
+
+ int recordCounter = 0;
+ while (resultIterator.hasNext()) {
+ final T record = resultIterator.next();
+ if (!matchThenNext(record)) {
+ duplicateRead.add(record);
+ } else {
+ recordCounter++;
+ }
+
+ if (limit != null && recordCounter >= limit) {
+ break;
+ }
+ }
+ if (limit == null && !hasReachedEnd()) {
+ failWithMessage(
+ generateMismatchDescription(
+ String.format(
+ "Expected to have at least %d records in
result, but only received %d records",
+ recordsFromSplits.stream()
+ .mapToInt(
+ recordsFromSplit ->
+
recordsFromSplit.records.size())
+ .sum(),
+ recordCounter),
+ resultIterator));
+ } else {
+ confirmDuplicateRead(duplicateRead);
+ }
+ }
+
+ private void compareWithExactlyOnceSemantic(
+ Iterator<T> resultIterator, List<RecordsFromSplit<T>>
expectedData) {
+ int recordCounter = 0;
+ while (resultIterator.hasNext()) {
+ final T recordReceived = resultIterator.next();
+ if (!matchThenNext(recordReceived)) {
+ if (recordCounter >= totalNumRecords) {
+ failWithMessage(
+ generateMismatchDescription(
+ String.format(
+ "Expected to have exactly %d
records in result, but received more records",
+ expectedData.stream()
+ .mapToInt(
+ recordsFromSplit ->
+
recordsFromSplit.records.size())
+ .sum()),
+ resultIterator));
+ } else {
+ failWithMessage(
+ generateMismatchDescription(
+ String.format(
+ "Unexpected record '%s' at
position %d(count of matched records)",
+ recordReceived, recordCounter),
+ resultIterator));
+ }
+ }
+ recordCounter++;
+ if (limit != null && recordCounter >= limit) {
+ break;
+ }
+ }
+ if (limit == null && !hasReachedEnd()) {
+ failWithMessage(
+ generateMismatchDescription(
+ String.format(
+ "Expected to have exactly %d records in
result, but only received %d records",
+ expectedData.stream()
+ .mapToInt(
+ recordsFromSplit ->
+
recordsFromSplit.records.size())
+ .sum(),
+ recordCounter),
+ resultIterator));
+ }
+ }
+
+ private void confirmDuplicateRead(List<T> duplicateRead) {
+ for (T record : duplicateRead) {
+ boolean found = false;
+ for (RecordsFromSplit<T> recordsFromSplit :
expectedRecordsFromSplits) {
+ if (recordsFromSplit.records.contains(record)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ failWithMessage(String.format("Unexpected duplicate record
'%s'", record));
+ }
+ }
+ }
+
+ /**
+ * Check if any pointing data is identical to the record from the stream,
and move the pointer
+ * to next record if matched.
+ *
+ * @param record Record from stream
+ */
+ private boolean matchThenNext(T record) {
+ for (RecordsFromSplit<T> recordsFromSplit : expectedRecordsFromSplits)
{
+ if (!recordsFromSplit.hasNext()) {
+ continue;
+ }
+ if (record.equals(recordsFromSplit.current())) {
+ recordsFromSplit.forward();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Whether all pointers have reached the end of lists.
+ *
+ * @return True if all pointers have reached the end.
+ */
+ private boolean hasReachedEnd() {
+ for (RecordsFromSplit<T> recordsFromSplit : expectedRecordsFromSplits)
{
+ if (recordsFromSplit.hasNext()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private String generateMismatchDescription(String reason, Iterator<T>
resultIterator) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(reason).append("\n");
+ sb.append("Current progress of multiple split test data
validation:\n");
+ int splitCounter = 0;
+ for (RecordsFromSplit<T> recordsFromSplit : expectedRecordsFromSplits)
{
+ sb.append(
+ String.format(
+ "Split %d (%d/%d): \n",
+ splitCounter++,
+ recordsFromSplit.offset,
+ recordsFromSplit.records.size()));
+ for (int recordIndex = 0;
+ recordIndex < recordsFromSplit.records.size();
+ recordIndex++) {
+ sb.append(recordsFromSplit.records.get(recordIndex));
+ if (recordIndex == recordsFromSplit.offset) {
+ sb.append("\t<---- failed to compare with the current
record");
+ }
+ sb.append("\n");
+ }
+ }
+ // Modify the following info building to avoid the test being stuck.
+ if (resultIterator.hasNext()) {
+ sb.append("Remaining received elements after the unexpected one:
xxx\n");
+ // while (resultIterator.hasNext()) {
+ // sb.append(resultIterator.next()).append("\n");
+ // }
+ }
+ return sb.toString();
+ }
+
+ private static class RecordsFromSplit<T> {
+ private int offset = 0;
+ private final List<T> records;
+
+ public RecordsFromSplit(List<T> records) {
+ this.records = records;
+ }
+
+ public T current() {
+ if (!hasNext()) {
+ return null;
+ }
+ return records.get(offset);
+ }
+
+ public void forward() {
+ ++offset;
+ }
+
+ public boolean hasNext() {
+ return offset < records.size();
+ }
+ }
+}
diff --git
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/testutils/function/ControlSource.java
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/testutils/function/ControlSource.java
index 63db956..fb9211f 100644
---
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/testutils/function/ControlSource.java
+++
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/testutils/function/ControlSource.java
@@ -25,7 +25,7 @@ import
org.apache.flink.connector.pulsar.testutils.runtime.PulsarRuntimeOperator
import org.apache.flink.runtime.state.FunctionInitializationContext;
import org.apache.flink.runtime.state.FunctionSnapshotContext;
import org.apache.flink.streaming.api.checkpoint.CheckpointedFunction;
-import org.apache.flink.streaming.api.functions.source.SourceFunction;
+import org.apache.flink.streaming.api.functions.source.legacy.SourceFunction;
import org.apache.flink.testutils.junit.SharedObjectsExtension;
import org.apache.flink.testutils.junit.SharedReference;
diff --git
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/testutils/runtime/container/PulsarContainerRuntime.java
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/testutils/runtime/container/PulsarContainerRuntime.java
index 9bd2252..2b93e79 100644
---
a/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/testutils/runtime/container/PulsarContainerRuntime.java
+++
b/flink-connector-pulsar/src/test/java/org/apache/flink/connector/pulsar/testutils/runtime/container/PulsarContainerRuntime.java
@@ -54,7 +54,7 @@ public class PulsarContainerRuntime implements PulsarRuntime {
private static final String PULSAR_ADMIN_URL =
String.format("http://%s:%d", PULSAR_INTERNAL_HOSTNAME,
BROKER_HTTP_PORT);
- private static final String CURRENT_VERSION = "3.0.5";
+ private static final String CURRENT_VERSION = "4.0.13";
private final PulsarContainer container;
private final AtomicBoolean started;
diff --git a/flink-sql-connector-pulsar/pom.xml
b/flink-sql-connector-pulsar/pom.xml
index 2c35bf0..3629707 100644
--- a/flink-sql-connector-pulsar/pom.xml
+++ b/flink-sql-connector-pulsar/pom.xml
@@ -76,10 +76,13 @@ under the License.
<include>org.apache.pulsar:pulsar-client-admin-api</include>
<include>org.apache.pulsar:pulsar-client-all</include>
<include>org.apache.pulsar:pulsar-client-api</include>
-
<include>org.bouncycastle:bcpkix-jdk15on</include>
-
<include>org.bouncycastle:bcprov-ext-jdk15on</include>
-
<include>org.bouncycastle:bcprov-jdk15on</include>
-
<include>org.bouncycastle:bcutil-jdk15on</include>
+
<include>org.bouncycastle:bcpkix-jdk18on</include>
+
<include>org.bouncycastle:bcprov-jdk18on</include>
+
<include>org.bouncycastle:bcutil-jdk18on</include>
+
<include>io.opentelemetry:opentelemetry-api</include>
+
<include>io.opentelemetry:opentelemetry-api-incubator</include>
+
<include>io.opentelemetry:opentelemetry-context</include>
+
<include>io.opentelemetry:opentelemetry-common</include>
</includes>
</artifactSet>
<filters>
diff --git a/flink-sql-connector-pulsar/src/main/resources/META-INF/NOTICE
b/flink-sql-connector-pulsar/src/main/resources/META-INF/NOTICE
index a36feb1..e9bc18f 100644
--- a/flink-sql-connector-pulsar/src/main/resources/META-INF/NOTICE
+++ b/flink-sql-connector-pulsar/src/main/resources/META-INF/NOTICE
@@ -6,15 +6,18 @@ The Apache Software Foundation (http://www.apache.org/).
This project bundles the following dependencies under the Apache Software
License 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
-- com.fasterxml.jackson.core:jackson-annotations:2.13.4
-- org.apache.pulsar:pulsar-client-admin-api:3.0.5
-- org.apache.pulsar:pulsar-client-all:3.0.5
-- org.apache.pulsar:pulsar-client-api:3.0.5
+- com.fasterxml.jackson.core:jackson-annotations:2.22
+- io.opentelemetry:opentelemetry-api:1.62.0
+- io.opentelemetry:opentelemetry-api-incubator:1.62.0-alpha
+- io.opentelemetry:opentelemetry-common:1.62.0
+- io.opentelemetry:opentelemetry-context:1.62.0
+- org.apache.pulsar:pulsar-client-admin-api:4.0.13
+- org.apache.pulsar:pulsar-client-all:4.0.13
+- org.apache.pulsar:pulsar-client-api:4.0.13
This project bundles the following dependencies under the Bouncy Castle
license.
See bundled license files for details.
-- org.bouncycastle:bcpkix-jdk15on:1.69
-- org.bouncycastle:bcprov-ext-jdk15on:1.69
-- org.bouncycastle:bcprov-jdk15on:1.69
-- org.bouncycastle:bcutil-jdk15on:1.69
+- org.bouncycastle:bcpkix-jdk18on:1.84
+- org.bouncycastle:bcprov-jdk18on:1.84
+- org.bouncycastle:bcutil-jdk18on:1.84
diff --git a/pom.xml b/pom.xml
index 685d8ec..5c98841 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,11 +51,10 @@ under the License.
</modules>
<properties>
- <flink.version>1.20.3</flink.version>
- <pulsar.version>3.0.5</pulsar.version>
+ <flink.version>2.0.2</flink.version>
+ <pulsar.version>4.0.13</pulsar.version>
+ <opentelemetry.version>1.62.0</opentelemetry.version>
<scala.binary.version>2.12</scala.binary.version>
- <bouncycastle.version>1.69</bouncycastle.version>
-
<scala-reflect.version>2.12.7</scala-reflect.version>
<scala-library.version>2.12.7</scala-library.version>
@@ -64,7 +63,7 @@ under the License.
<assertj.version>3.23.1</assertj.version>
<mockito.version>4.11.0</mockito.version>
<archunit.version>1.0.1</archunit.version>
- <testcontainers.version>1.21.4</testcontainers.version>
+ <testcontainers.version>2.0.4</testcontainers.version>
<japicmp.skip>false</japicmp.skip>
<japicmp.referenceVersion>3.0.0-1.16</japicmp.referenceVersion>
@@ -76,10 +75,13 @@ under the License.
<commons-compress.version>1.26.1</commons-compress.version>
<commons-lang3.version>3.14.0</commons-lang3.version>
<commons-io.version>2.15.1</commons-io.version>
+ <caffeine.version>2.9.1</caffeine.version>
+ <checker-qual.version>3.12.0</checker-qual.version>
+ <errorprone.version>2.11.0</errorprone.version>
<byte-buddy.version>1.12.20</byte-buddy.version>
<kryo.version>2.24.0</kryo.version>
<objenesis.version>3.3</objenesis.version>
- <jackson-bom.version>2.13.4.20221013</jackson-bom.version>
+ <jackson-bom.version>2.22.2</jackson-bom.version>
<snappy.java.version>1.1.10.4</snappy.java.version>
<os-maven-plugin.version>1.7.0</os-maven-plugin.version>
@@ -134,7 +136,7 @@ under the License.
<dependency>
<groupId>org.testcontainers</groupId>
- <artifactId>junit-jupiter</artifactId>
+ <artifactId>testcontainers-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
@@ -391,6 +393,18 @@ under the License.
<version>${jackson-bom.version}</version>
</dependency>
+ <dependency>
+ <groupId>io.opentelemetry</groupId>
+ <artifactId>opentelemetry-api</artifactId>
+ <version>${opentelemetry.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>io.opentelemetry</groupId>
+ <artifactId>opentelemetry-api-incubator</artifactId>
+ <version>${opentelemetry.version}-alpha</version>
+ </dependency>
+
<!-- Start of pinned versions for dependency convergence -->
<dependency>
@@ -411,6 +425,24 @@ under the License.
<version>${commons-io.version}</version>
</dependency>
+ <dependency>
+ <groupId>com.github.ben-manes.caffeine</groupId>
+ <artifactId>caffeine</artifactId>
+ <version>${caffeine.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.checkerframework</groupId>
+ <artifactId>checker-qual</artifactId>
+ <version>${checker-qual.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.errorprone</groupId>
+ <artifactId>error_prone_annotations</artifactId>
+ <version>${errorprone.version}</version>
+ </dependency>
+
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>