This is an automated email from the ASF dual-hosted git repository.
davidzollo pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/seatunnel.git
The following commit(s) were added to refs/heads/dev by this push:
new fc8e2204b5 [Test][E2E] Bound Pulsar sink IT receive wait (#11159)
fc8e2204b5 is described below
commit fc8e2204b5e53548be889b0b4b2b45d93af3721f
Author: Daniel <[email protected]>
AuthorDate: Thu Jul 2 23:10:56 2026 +0800
[Test][E2E] Bound Pulsar sink IT receive wait (#11159)
Co-authored-by: DanielLeens <[email protected]>
---
.../e2e/connector/pulsar/PulsarSinkIT.java | 117 +++++++++++++--------
1 file changed, 75 insertions(+), 42 deletions(-)
diff --git
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-pulsar-e2e/src/test/java/org/apache/seatunnel/e2e/connector/pulsar/PulsarSinkIT.java
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-pulsar-e2e/src/test/java/org/apache/seatunnel/e2e/connector/pulsar/PulsarSinkIT.java
index 9a9201f341..49a3550025 100644
---
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-pulsar-e2e/src/test/java/org/apache/seatunnel/e2e/connector/pulsar/PulsarSinkIT.java
+++
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-pulsar-e2e/src/test/java/org/apache/seatunnel/e2e/connector/pulsar/PulsarSinkIT.java
@@ -39,7 +39,7 @@ import org.testcontainers.shaded.org.awaitility.Awaitility;
import lombok.extern.slf4j.Slf4j;
-import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
@@ -53,7 +53,17 @@ public class PulsarSinkIT extends TestSuiteBase implements
TestResource {
private static final String PULSAR_IMAGE_NAME =
"apachepulsar/pulsar:2.3.1";
public static final String PULSAR_HOST = "pulsar.e2e.sink";
- public static final String TOPIC = "topic_test02";
+ private static final String TOPIC = "topic_test02";
+
+ /** Expected record count produced by fake_to_pulsar.conf. */
+ private static final int EXPECTED_RECORD_COUNT = 10;
+
+ /** Total time budget for draining sink output before failing the test. */
+ private static final Duration RECEIVE_TIMEOUT = Duration.ofSeconds(60);
+
+ /** Single receive poll timeout to avoid blocking the CI job forever. */
+ private static final int RECEIVE_POLL_TIMEOUT_SECONDS = 5;
+
private PulsarContainer pulsarContainer;
@Override
@@ -83,51 +93,74 @@ public class PulsarSinkIT extends TestSuiteBase implements
TestResource {
pulsarContainer.close();
}
- private List<String> getPulsarConsumerData() {
- List<String> data = new ArrayList<>();
- try {
- PulsarClient client =
-
PulsarClient.builder().serviceUrl(pulsarContainer.getPulsarBrokerUrl()).build();
-
- Random random = new Random();
- Consumer consumer =
- client.newConsumer()
- .topic(TOPIC)
- .subscriptionName("PulsarSubTest" +
random.nextInt())
- .subscriptionType(SubscriptionType.Exclusive)
-
.subscriptionInitialPosition(SubscriptionInitialPosition.Earliest)
- .subscribe();
- for (int i = 0; i < 10; i++) {
- Message msg = consumer.receive(30, TimeUnit.SECONDS);
- if (msg != null) {
- data.add(new String(msg.getData()));
- consumer.acknowledge(msg.getMessageId());
- log.info("value:{}", new String(msg.getData()));
- } else {
- log.warn("No message received within timeout, received {}
so far", data.size());
- break;
- }
+ /** Create a dedicated client for the broker exposed by the test
container. */
+ private PulsarClient createPulsarClient() throws Exception {
+ return
PulsarClient.builder().serviceUrl(pulsarContainer.getPulsarBrokerUrl()).build();
+ }
+
+ /**
+ * Subscribe to the sink topic before the batch job starts so the
assertion cannot miss records
+ * because the producer finished before the consumer began polling.
+ */
+ private Consumer<byte[]> createPulsarConsumer(PulsarClient client) throws
Exception {
+ return client.newConsumer()
+ .topic(TOPIC)
+ .subscriptionName("PulsarSubTest" + new Random().nextInt())
+ .subscriptionType(SubscriptionType.Exclusive)
+
.subscriptionInitialPosition(SubscriptionInitialPosition.Earliest)
+ .subscribe();
+ }
+
+ /**
+ * Consume the records written by the sink job without leaving the test
stuck in a blocking
+ * receive call when CI delivery is delayed.
+ */
+ private List<String> getPulsarConsumerData(Consumer<byte[]> consumer)
throws Exception {
+ List<String> data = new ArrayList<>(EXPECTED_RECORD_COUNT);
+ long deadlineNanos = System.nanoTime() + RECEIVE_TIMEOUT.toNanos();
+ while (data.size() < EXPECTED_RECORD_COUNT && System.nanoTime() <
deadlineNanos) {
+ Message<byte[]> msg =
consumer.receive(RECEIVE_POLL_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ if (msg == null) {
+ continue;
}
- } catch (Exception e) {
- throw new RuntimeException("Failed to get pulsar consumer data",
e);
+
+ String value = new String(msg.getData(), StandardCharsets.UTF_8);
+ data.add(value);
+ consumer.acknowledge(msg);
+ log.info("value:{}", value);
+ }
+
+ if (data.size() < EXPECTED_RECORD_COUNT) {
+ log.warn(
+ "Timed out waiting for {} Pulsar sink records, only
consumed {}",
+ EXPECTED_RECORD_COUNT,
+ data.size());
}
return data;
}
@TestTemplate
- public void testSinkPulsar(TestContainer container) throws IOException,
InterruptedException {
- Container.ExecResult execResult =
container.executeJob("/fake_to_pulsar.conf");
- Assertions.assertEquals(execResult.getExitCode(), 0);
-
- List<String> data = getPulsarConsumerData();
- log.info("data size:{}", data.size());
- ObjectMapper objectMapper = new ObjectMapper();
- ObjectNode objectNode = objectMapper.readValue(data.get(0),
ObjectNode.class);
- Assertions.assertTrue(objectNode.has("c_map"));
- Assertions.assertTrue(objectNode.has("c_array"));
- Assertions.assertTrue(objectNode.has("c_string"));
- Assertions.assertTrue(objectNode.has("c_boolean"));
- Assertions.assertTrue(objectNode.has("c_double"));
- Assertions.assertEquals(10, data.size());
+ public void testSinkPulsar(TestContainer container) throws Exception {
+ try (PulsarClient client = createPulsarClient();
+ Consumer<byte[]> consumer = createPulsarConsumer(client)) {
+ Container.ExecResult execResult =
container.executeJob("/fake_to_pulsar.conf");
+ Assertions.assertEquals(execResult.getExitCode(), 0);
+
+ List<String> data = getPulsarConsumerData(consumer);
+ log.info("data size:{}", data.size());
+ Assertions.assertEquals(
+ EXPECTED_RECORD_COUNT,
+ data.size(),
+ String.format(
+ "Expected %d Pulsar records within %d seconds but
received %d",
+ EXPECTED_RECORD_COUNT,
RECEIVE_TIMEOUT.getSeconds(), data.size()));
+ ObjectMapper objectMapper = new ObjectMapper();
+ ObjectNode objectNode = objectMapper.readValue(data.get(0),
ObjectNode.class);
+ Assertions.assertTrue(objectNode.has("c_map"));
+ Assertions.assertTrue(objectNode.has("c_array"));
+ Assertions.assertTrue(objectNode.has("c_string"));
+ Assertions.assertTrue(objectNode.has("c_boolean"));
+ Assertions.assertTrue(objectNode.has("c_double"));
+ }
}
}