-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PIP-12 Introduce builder for creating Producer Consumer Reader #1089
Conversation
/cc @lucperkins |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the proposed api looks good me. but it seems some of the javadocs were copied from configuration based methods, we need to update the javadoc for those methods.
* | ||
* <pre> | ||
* <code> | ||
* ClientConfiguration conf = new ClientConfiguration(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
documentation seems need to be updated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, this was just a placeholder. I'll clean up all Javadocs when submitting final PR.
+1, LGTM, currently. |
|
||
public interface ProducerBuilder { | ||
|
||
Producer create() throws PulsarClientException; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: since this is a builder, do we want to go with the canonical 'build' terminology instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I was debating about this. My reasoning here was to differentiate the actions:
client.newProducer().topic(MY_TOPIC).create();
// versus
client.newConsumer().topic(MY_TOPIC).subscriptionName(MY_SUB).subscribe();
Subscribe here implies to create a durable Subscription
on the topic, not just building an ephemeral Consumer
instance.
I'm not 100% settled on this. Please anyone share opinions ;)
|
||
Producer create() throws PulsarClientException; | ||
|
||
CompletableFuture<Producer> createAsync(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like having async and sync versions cloud things. The nature of the library is that it is async and if all we are doing is calling CompletableFuture::get
and catching exceptions for the user, is it really worth it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think most users still reasons in term of "sync" API, especially for creating the producer/consumer (compared to publishing messages).
The other doubt here was which form would be preferred between: Producer producer = client.newProducer().topic("my-topic").create(); versus Producer producer = client.newProducer("my-topic").create(); This is regarding required and optional parameters. The 2nd is a bit more concise, though that doesn't mean a lot if you're setting multiple options anyway. Opinions with respect to this? |
f5ee1fe
to
f17cac1
Compare
This is ready for review. Once this is finalized and merged, I'll start converting all the code to use new API. |
Yes, the idea was to have different ways to specify: // Single topic
client.newConsumer().topic(MY_TOPIC).subscriptioName(SUB).build();
// List of topics
List<String> myList = ...;
client.newConsumer().topics(myList).subscriptioName(SUB).build();
// Regex
client.newConsumer().topicsRegex("test.*").subscriptioName(SUB).build(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the change looks good to me. some minor comments.
it is a really awesome change to move the api to builder pattern!
import org.apache.pulsar.client.api.PulsarClientException.UnsupportedAuthenticationException; | ||
|
||
/** | ||
* Builder interface that is used to construct a {@link PulsarClient} instance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: it might be good to add "@SInCE 2.0". so we can track when we introduce the build methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, will add @since
* PulsarClient client2 = builder.clone().serviceUrl(URL_2).build(); | ||
* </pre> | ||
*/ | ||
ClientBuilder clone(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: @Override
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clone()
is a bit weird in the way it's treated. It cannot be marked as @Override
* Finalize the consumer creation by subscribing to the topic. | ||
* | ||
* <p> | ||
* Subscribing to the c |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
incomplete comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ups, forgot to finish
* <p> | ||
* Subscribing to the c | ||
* | ||
* @return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@return a consumer
?
* | ||
* @param The consumer action | ||
* | ||
* @param The |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the param field seems to be wrong?
* | ||
* @param topicName | ||
*/ | ||
ConsumerBuilder topic(String topicName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's just an idea but we may want to pass a Topic object instead of its string representation. Then this interface would be freed to define a format of topic name string (persistent://.../.../...), and users can manage their topic names in any format.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would leave it as a string, at least for now, because that would be a bigger change I think. We're already trying to address the long topic names by having some degree of implicitenes. See https://github.com/apache/incubator-pulsar/wiki/PIP-10:-Remove-cluster-for-namespace-and-topic-names and https://github.com/apache/incubator-pulsar/wiki/PIP-11:-Short-topic-names
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright. Yeah, and the change is not necessary for introducing builders.
Below is what I thought.
We should probably introduce a parser for topic name string to reduce duplicate parsing code. Otherwise PIP-10 and PIP-11 would be tough because we need to modify all parsing code here and there. If we introduce the parser, the builder implementation would be like:
public ConsumerBuilder topic(String topicName) {
this.topic = Topic.parse(topicName);
return this;
}
The Topic class would be like this:
class Topic {
public Topic(String topicName) {
// parse
...
this.namespace = ....
this.cluster = ...
...
}
public getNamespace() {
return this.namespace;
}
...
}
Once we did this, other components that use Topic object wouldn't need to care how the object was created. And if so, it might be useful if users could create own Topic implementation and pass it to builders.
So I'm not saying we should eliminate the Pulsar topic URL format. I just thought using Topic object may increase its capability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For parsing, it's already all concentrated in the DestinationName
class, which I plan to rename into TopicName
. It is not exposed to users though.
* | ||
* @param tlsAllowInsecureConnection | ||
*/ | ||
ClientBuilder tlsAllowInsecureConnection(boolean tlsAllowInsecureConnection); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about "allowTlsInsecureConnection"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, with the builder it makes sense a more "imperative" style
* | ||
* @param enableTLS | ||
*/ | ||
ClientBuilder enableTLS(boolean enableTLS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"TLS"? or "Tls"? Need consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I'll go back back to "Tls"
@@ -377,7 +377,8 @@ public void removeEncryptionKey(String key) { | |||
/** | |||
* Sets the ProducerCryptoFailureAction to the value specified | |||
* | |||
* @param The producer action | |||
* @param The |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing a parameter name
retest this please |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
585dd9b
to
03dcd22
Compare
Rebased to fix tls test certificates issue |
Since the apache#1089,the interface 'org.apache.pulsar.client.api.PulsarClient' has supported builder for consumer and producer. And,int the apache#3272, some deprecated client API have been removed including 'public static PulsarClient create(String serviceUrl)','Consumer<byte[]> subscribe(String topic, String subscription)' and 'Producer<byte[]> createProducer(String topic)'. So, I modified the example with the current version of the interface.
* Update concepts-messaging.md Since the #1089,the interface 'org.apache.pulsar.client.api.PulsarClient' has supported builder for consumer and producer. And,int the #3272, some deprecated client API have been removed including 'public static PulsarClient create(String serviceUrl)','Consumer<byte[]> subscribe(String topic, String subscription)' and 'Producer<byte[]> createProducer(String topic)'. So, I modified the example with the current version of the interface. * Apply suggestions from code review Specify message schema Co-Authored-By: Matteo Merli <mmerli@apache.org>
Motivation
Full context at
https://github.com/apache/incubator-pulsar/wiki/PIP-12:-Introduce-builder-for-creating-Producer-Consumer-Reader
Modifications