-
Notifications
You must be signed in to change notification settings - Fork 77
[feature] Support set ServiceUrlProvider when create client. #170
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
Conversation
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.
We only need to support passing a std::function<std::string()>. The initialize and close methods are redundant. IMO, the interface was not designed well in Java caused by the abuse of virtual functions. It makes it impossible to use a lambda as the service URL provider in Java.
If you really want to wrap the initialization and close logics, you can implement the function like:
class ServiceUrlProvider {
public:
ServiceUrlProvider(/* we can pass any type we want */) { /* initializations ... */ }
void close() {/* close the resource... */}
std:string operator()() const { /* ... */ }
};For example, if we need to load the available URLs from a file periodically, we can pass the file path in the constructor and close the files in close.
There are also internal implementations in Java client like AutoClusterFailover. However, it actually makes use of PulsarClientImpl, not PulsarClient.
Yes, you are right. The initialize and close methods are redundant. In fact, The client already provides the I changed to pass a |
cd94e93 to
be414f7
Compare
| /** | ||
| * Create a Pulsar client object connecting to the specified cluster address and using the default | ||
| * configuration. | ||
| * | ||
| * <p>Instead of specifying a static service URL string (with {@link #serviceUrl(String)}), an application | ||
| * can pass a {@link ServiceUrlProvider} function that dynamically provide a service URL. | ||
| * | ||
| * @param serviceUrlProvider The serviceUrlProvider used to generate ServiceUrl. | ||
| * @throw std::invalid_argument if `serviceUrlProvider()` return a invalid url. | ||
| */ | ||
| Client(ServiceUrlProvider serviceUrlProvider); |
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.
| /** | |
| * Create a Pulsar client object connecting to the specified cluster address and using the default | |
| * configuration. | |
| * | |
| * <p>Instead of specifying a static service URL string (with {@link #serviceUrl(String)}), an application | |
| * can pass a {@link ServiceUrlProvider} function that dynamically provide a service URL. | |
| * | |
| * @param serviceUrlProvider The serviceUrlProvider used to generate ServiceUrl. | |
| * @throw std::invalid_argument if `serviceUrlProvider()` return a invalid url. | |
| */ | |
| Client(ServiceUrlProvider serviceUrlProvider); | |
| /** | |
| * @see Client(ServiceUrlProvider, const ClientConfiguration&) | |
| */ | |
| Client(ServiceUrlProvider serviceUrlProvider) : Client(serviceUrlProvider, ClientConfiguration{}) {} |
Avoid unnecessary duplicated code and API docs.
I reviewed the If we want to implement
The way of using For C++ client, this PR implements the similar way with Java that the ServiceUrlProvider provider = /* ... */;
Client client(provider());and ServiceUrlProvider provider = /* ... */;
String serviceUrl = provider();
Client client(serviceUrl);l'm going to send an email to dev mail list to discuss. |
Yes, Actually, the If we do not expose the set Use Client client([]() {
// get service URL from store.
auto serviceUrl = xxx
return serviceUrl;
})
// get service URL from store.
auto serviceUrl = xxx
Client client(serviceUrl);I exposed it just for ease of use. |
|
If you feel redundant to expose this method, I can remove it. What do you think? /cc @BewareMyPower |
|
I have sent an email: https://lists.apache.org/thread/cojz6qxpc7v0j8vy0w476ttt0f89zr3z |
|
In short, a natural design is to save the |
I think only need the client to provide the Users can take advantage of this approach to implement their own services. (Pseudocode) class Store;
class AutomaticClusterService {
public:
explicit AutomaticClusterService(const Store& store, const Client pulsarClient)
: store_(store), pulsarClient_(pulsarClient) {
serviceUrlCache_ = store.queryServiceUrl();
updateServiceUrlInterval_ = boost::posix_time::seconds(60);
runUpdateServiceurl();
}
void start() {
runUpdateServiceurl();
}
const std::string& getServiceUrl(){
return serviceUrlCache_;
}
const void runUpdateServiceurl() {
timer_->expires_from_now(updateServiceUrlInterval_);
auto availableServiceUrl = store_.queryServiceUrl();
timer_->async_wait([this](const boost::system::error_code& ec) {
// Maybe some other implementation
if (serviceUrlCache_ != availableServiceUrl) {
serviceUrlCache_ = availableServiceUrl;
pulsarClient_.updateServiceUrl(serviceUrlCache_);
}
runUpdateServiceurl();
});
}
private:
// External storage services
Store store_;
const Client pulsarClient_;
std::string serviceUrlCache_;
std::shared_ptr<boost::asio::deadline_timer> timer_;
boost::posix_time::time_duration updateServiceUrlInterval_;
};
Store store;
Client client(store.queryServiceUrl());
AutomaticClusterService automaticClusterService(store, client);
automaticClusterService.start();
//....
|
This idea also looks good to me. |
|
@shibd We should delay this feature until a result of this discussion. |
|
Close this PR for now. |
Master Issue: apache/pulsar#2543
Motivation
#163
ServiceUrlProvideris provided so that users can dynamically update serviceUrl, and can be implemented #164 cluster level auto failover.Modifications
ServiceUrlProviderfunction define.updateServiceUrlmethod in the Client.Clientadd new constructor method to support setServiceUrlProviderinstance param.Verifying this change
ServiceUrlProviderTestto cover customServiceUrlProvider.Documentation
doc-required(Your PR needs to update docs and you will update later)
doc-not-needed(Please explain why)
doc(Your PR contains doc changes)
doc-complete(Docs have been already added)