Skip to content

debezium/dbz#1098 Add Qdrant connection validator#280

Merged
mfvitale merged 9 commits intodebezium:mainfrom
gmarav05:dbz-1098-Qdrant-sink-connection-validator
Mar 26, 2026
Merged

debezium/dbz#1098 Add Qdrant connection validator#280
mfvitale merged 9 commits intodebezium:mainfrom
gmarav05:dbz-1098-Qdrant-sink-connection-validator

Conversation

@gmarav05
Copy link
Copy Markdown
Contributor

@gmarav05 gmarav05 commented Mar 3, 2026

Adds Qdrant Sink Connection Validator DBZ-9441

Summary

This PR adds support for validating Qdrant Sink connections.

Changes

  1. Implements QdrantConnectionValidator for checking connectivity to Qdrant.
  2. Adds QDRANT type to ConnectionEntity.Type enum.
  3. Updates connection-schemas.json with Qdrant connection schema.
  4. Added integration test for Qdrant connection validation.

Testing:

  • It also includes integration tests for both valid and invalid Qdrant connection configurations.

Fixes debezium/dbz#1098 DBZ-9441

"title": "Protocol to use (http or https)",
"default": "http"
},
"apiKey": {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is apiKey used?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, the apiKey property is not used in the validator implementation.

I included it in the schema for future support of Qdrant API key authentication, but since it is not being used, We can remove it to avoid confusion.

Let me know if you prefer it removed or if you would like me to add support for API key in the validator.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If possible I'd prefer to add the support. Also if you can rename it to api.key.

@mfvitale Do you agree?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah sure no problem I will add support, I will wait for the approval.

Copy link
Copy Markdown
Member

@mfvitale mfvitale Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we should add support also for api.key

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If possible I'd prefer to add the support. Also if you can rename it to api.key.

@mfvitale Do you agree?

yeah sure @jpechane @mfvitale , I will add support for the api.key property in the validator and update the schema accordingly.

RABBITMQ_STREAM,
RABBITMQ_NATIVE_STREAM,
MILVUS,
@JsonProperty("QDRANT")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you clarify why you added the annotation here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah sure, I added the "QDRANT" annotation for consistency with other enum values that use custom JSON names.

If it is not needed for Qdrant, I can remove it.

@Override
public ConnectionValidationResult validate(Connection connectionConfig) {
Map<String, Object> config = connectionConfig.getConfig();
String host = (String) config.getOrDefault("host", "localhost");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you reason why localhost should be a good default here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay So localhost was used as a default to allow local development and testing out of the box.

I am planning to remove that.

URL url = new URL(healthEndpoint);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(3000);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a configuration property for these timeouts like in

public KafkaConnectionValidator(@ConfigProperty(name = "destinations.kafka.connection.timeout") int defaultConnectionTimeout) {
?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah sure i started working on this I will refactor the validator to use a configuration property for timeouts, similar to the Kafka validator, to allow users to customize connection timeouts.

thanks for the reference!

"protocol": {
"type": "string",
"title": "Protocol to use (http or https)",
"default": "http"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is currently not supported but it is an interesting idea.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, the protocol property is not supported, but I agree it is a useful idea.

I can leave it in the schema for future support or remove it for now, based on your preference @jpechane @mfvitale.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to remove it to avoid confusion.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah sure i will remove this asap.

@gmarav05 gmarav05 requested review from jpechane and mfvitale March 9, 2026 08:30
@gmarav05
Copy link
Copy Markdown
Contributor Author

Hi @jpechane @mfvitale, Could you please take another look and Re run the CI.

}

String apiKey = getString(config, API_KEY);
String healthEndpoint = protocol + "://" + host + ":" + port + "/healthz";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WDYT to define a endpoint format string and the use "".formatted to pass the parameters?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a great idea, I will update the validator to define health endpoint format constant and switch to .formatted(host, port) when building the URL for clarity and maintainability.

public class QdrantConnectionValidatorIT {

@Test
public void testValidate_withValidConfig_shouldReturnSuccessOrFailure() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well effectively this is not a meaningful test. You shoul start a qdrant container and test the real connectivity. I suggest to have a look to what has been done with AzureEventHubsTestResource

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion. I now replaced the previous Qdrant IT with a real Testcontainers based integration test and added a dedicated QdrantTestResource just like AzureEventHubsTestResource.

The test now validates connectivity against a running Qdrant container using the actual mapped host/port.

Comment on lines +62 to +74
URL url = new URL(healthEndpoint);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout((int) Duration.ofSeconds(defaultConnectionTimeout).toMillis());
conn.setReadTimeout((int) Duration.ofSeconds(defaultConnectionTimeout).toMillis());
if (!isBlank(apiKey)) {
conn.setRequestProperty("api-key", apiKey);
}
int responseCode = conn.getResponseCode();
if (responseCode == 200) {
return ConnectionValidationResult.successful();
}
return ConnectionValidationResult.failed("Qdrant health check failed with status: " + responseCode);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe you could wrap this into a method?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah sure Thank you for the feedback @mfvitale

Copy link
Copy Markdown
Member

@mfvitale mfvitale left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @gmarav05 Overall it LGTM. I just left a minor comment.

Copy link
Copy Markdown
Contributor

@jpechane jpechane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gmarav05 I left last minor comment, when addressed we are good to go.

}

@Test
public void testValidate_withValidConfig_shouldReturnSuccess() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use undersocres in identifier

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah sure i will make changes to this and update it. thank you @jpechane

@gmarav05
Copy link
Copy Markdown
Contributor Author

@gmarav05 I left last minor comment, when addressed we are good to go.

Sure, Sorry for the delay I had emergency. I was not active. I will start working.

@gmarav05 gmarav05 force-pushed the dbz-1098-Qdrant-sink-connection-validator branch from 0e71677 to 80a1ad5 Compare March 19, 2026 16:37
@gmarav05
Copy link
Copy Markdown
Contributor Author

hello @jpechane , @mfvitale. Can you please review my PR. Please let me know if any changes are required I mostly fixed all the issues from feedback.

@mfvitale
Copy link
Copy Markdown
Member

@gmarav05 Could you please rebase with main?

@gmarav05
Copy link
Copy Markdown
Contributor Author

@gmarav05 Could you please rebase with main?

yeah sure @mfvitale .

@github-actions
Copy link
Copy Markdown

Hi @gmarav05, thanks for your contribution. Please prefix the commit message(s) with the debezium/dbz#xxx GitHub issue key.

@gmarav05 gmarav05 force-pushed the dbz-1098-Qdrant-sink-connection-validator branch from a7cb1a5 to 039b501 Compare March 20, 2026 09:06
}
}

private static String getString(Map<String, Object> config, String key) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you use the method that are now in ConnectionConfigUtils?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah sure

"type": "object",
"required": [
"host",
"hostname",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems this is not correct.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooops I will fix it asap.

Copy link
Copy Markdown
Member

@mfvitale mfvitale Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change should not be there.

@gmarav05 gmarav05 force-pushed the dbz-1098-Qdrant-sink-connection-validator branch from f168fd6 to bd58189 Compare March 20, 2026 11:03
}

Integer port = ConnectionConfigUtils.getInteger(config, PORT);
if (port == null || port <= 0) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mfvitale Doesn't ignoring of negative port go against the validation prnicpile?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Yes, we should avoid putting defaults. This is something that could be done by the UI if we want but for sure not here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @jpechane , @mfvitale, Thank you for bringing this up. I have updated the validator to return a failure instead of defaulting to port 6333. Defaults should be handled by the UI, not the validator. by adding this return ConnectionValidationResult.failed("Port must be specified and must be a positive number for Qdrant connection"); WDYT.

Copy link
Copy Markdown
Contributor

@jpechane jpechane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gmarav05 @mfvitale I left one question. When answered/addresed this is good to go.

@gmarav05
Copy link
Copy Markdown
Contributor Author

gmarav05 commented Mar 24, 2026

@gmarav05 @mfvitale I left one question. When answered/addresed this is good to go.

Hello @jpechane. I have locally updated the validator to return a failure instead of defaulting to port 6333. Defaults should be handled by the UI, not the validator. by adding this return ConnectionValidationResult.failed("Port must be specified and must be a positive number for Qdrant connection"); Please let me know if this is correct approach.

@mfvitale
Copy link
Copy Markdown
Member

mfvitale commented Mar 24, 2026

@gmarav05 Could you please rebase with latest changes on main?

Signed-off-by: Aravind <gmarav005@gmail.com>
Signed-off-by: Aravind <gmarav005@gmail.com>
Qdrant connection validator

Signed-off-by: Aravind <gmarav005@gmail.com>
Signed-off-by: Aravind <gmarav005@gmail.com>
test

Signed-off-by: Aravind <gmarav005@gmail.com>
…ator

Signed-off-by: Aravind <gmarav005@gmail.com>
…of defaulting

Signed-off-by: Aravind <gmarav005@gmail.com>
@gmarav05 gmarav05 force-pushed the dbz-1098-Qdrant-sink-connection-validator branch from b6507ac to e5653a5 Compare March 24, 2026 12:19
@gmarav05
Copy link
Copy Markdown
Contributor Author

@gmarav05 Could you please rebase with latest changes on main?

Yeah sure @mfvitale , I rebased it now with main.

@mfvitale
Copy link
Copy Markdown
Member

@gmarav05 one last this to fix and then this could be merged.

…is host key

Signed-off-by: Aravind <gmarav005@gmail.com>
@gmarav05 gmarav05 requested a review from mfvitale March 26, 2026 09:15
@gmarav05
Copy link
Copy Markdown
Contributor Author

@gmarav05 one last this to fix and then this could be merged.

I have now fixed that in schema. Thank you @mfvitale

@mfvitale
Copy link
Copy Markdown
Member

@gmarav05 LGTM. When CI passes it can be merged

@mfvitale
Copy link
Copy Markdown
Member

@gmarav05 Applied, thanks!

@mfvitale mfvitale merged commit 03164b7 into debezium:main Mar 26, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add connection validator for Qdrant Sink [DBZ-9441]

4 participants