1818 */
1919#pragma once
2020
21- #include < algorithm>
22- #include < memory>
23-
24- #include " Backoff.h"
25- #include " ExecutorService.h"
26- #include " LogUtils.h"
2721#include " LookupDataResult.h"
2822#include " LookupService.h"
29- #include " SynchronizedHashMap.h"
23+ #include " NamespaceName.h"
24+ #include " RetryableOperationCache.h"
3025#include " TopicName.h"
3126
3227namespace pulsar {
3328
34- class RetryableLookupService : public LookupService ,
35- public std::enable_shared_from_this<RetryableLookupService> {
29+ class RetryableLookupService : public LookupService {
3630 private:
37- friend class PulsarFriend ;
31+ friend class LookupServiceTest ;
3832 struct PassKey {
3933 explicit PassKey () {}
4034 };
@@ -44,123 +38,58 @@ class RetryableLookupService : public LookupService,
4438 explicit RetryableLookupService (PassKey, Args&&... args)
4539 : RetryableLookupService(std::forward<Args>(args)...) {}
4640
41+ void close () override {
42+ lookupCache_->clear ();
43+ partitionLookupCache_->clear ();
44+ namespaceLookupCache_->clear ();
45+ getSchemaCache_->clear ();
46+ }
47+
4748 template <typename ... Args>
4849 static std::shared_ptr<RetryableLookupService> create (Args&&... args) {
4950 return std::make_shared<RetryableLookupService>(PassKey{}, std::forward<Args>(args)...);
5051 }
5152
5253 LookupResultFuture getBroker (const TopicName& topicName) override {
53- return executeAsync<LookupResult> (" get-broker-" + topicName.toString (),
54- [this , topicName] { return lookupService_->getBroker (topicName); });
54+ return lookupCache_-> run (" get-broker-" + topicName.toString (),
55+ [this , topicName] { return lookupService_->getBroker (topicName); });
5556 }
5657
5758 Future<Result, LookupDataResultPtr> getPartitionMetadataAsync (const TopicNamePtr& topicName) override {
58- return executeAsync<LookupDataResultPtr> (
59+ return partitionLookupCache_-> run (
5960 " get-partition-metadata-" + topicName->toString (),
6061 [this , topicName] { return lookupService_->getPartitionMetadataAsync (topicName); });
6162 }
6263
6364 Future<Result, NamespaceTopicsPtr> getTopicsOfNamespaceAsync (
6465 const NamespaceNamePtr& nsName, CommandGetTopicsOfNamespace_Mode mode) override {
65- return executeAsync<NamespaceTopicsPtr> (
66+ return namespaceLookupCache_-> run (
6667 " get-topics-of-namespace-" + nsName->toString (),
6768 [this , nsName, mode] { return lookupService_->getTopicsOfNamespaceAsync (nsName, mode); });
6869 }
6970
7071 Future<Result, SchemaInfo> getSchema (const TopicNamePtr& topicName, const std::string& version) override {
71- return executeAsync<SchemaInfo> (" get-schema" + topicName->toString (), [this , topicName, version] {
72+ return getSchemaCache_-> run (" get-schema" + topicName->toString (), [this , topicName, version] {
7273 return lookupService_->getSchema (topicName, version);
7374 });
7475 }
7576
76- template <typename T>
77- Future<Result, T> executeAsync (const std::string& key, std::function<Future<Result, T>()> f) {
78- Promise<Result, T> promise;
79- executeAsyncImpl (key, f, promise, timeout_);
80- return promise.getFuture ();
81- }
82-
8377 private:
8478 const std::shared_ptr<LookupService> lookupService_;
85- const TimeDuration timeout_;
86- Backoff backoff_;
87- const ExecutorServiceProviderPtr executorProvider_;
88-
89- SynchronizedHashMap<std::string, DeadlineTimerPtr> backoffTimers_;
79+ RetryableOperationCachePtr<LookupResult> lookupCache_;
80+ RetryableOperationCachePtr<LookupDataResultPtr> partitionLookupCache_;
81+ RetryableOperationCachePtr<NamespaceTopicsPtr> namespaceLookupCache_;
82+ RetryableOperationCachePtr<SchemaInfo> getSchemaCache_;
9083
9184 RetryableLookupService (std::shared_ptr<LookupService> lookupService, int timeoutSeconds,
9285 ExecutorServiceProviderPtr executorProvider)
9386 : lookupService_(lookupService),
94- timeout_ (boost::posix_time::seconds(timeoutSeconds)),
95- backoff_(boost::posix_time::milliseconds(100 ), timeout_ + timeout_,
96- boost::posix_time::milliseconds(0 )),
97- executorProvider_(executorProvider) {}
98-
99- std::weak_ptr<RetryableLookupService> weak_from_this () noexcept { return shared_from_this (); }
100-
101- // NOTE: Set the visibility to fix compilation error in GCC 6
102- template <typename T>
103- #ifndef _WIN32
104- __attribute__ ((visibility(" hidden" )))
105- #endif
106- void
107- executeAsyncImpl (const std::string& key, std::function<Future<Result, T>()> f, Promise<Result, T> promise,
108- TimeDuration remainingTime) {
109- auto weakSelf = weak_from_this ();
110- f ().addListener ([this , weakSelf, key, f, promise, remainingTime](Result result, const T& value) {
111- auto self = weakSelf.lock ();
112- if (!self) {
113- return ;
114- }
115-
116- if (result == ResultOk) {
117- backoffTimers_.remove (key);
118- promise.setValue (value);
119- } else if (result == ResultRetryable) {
120- if (remainingTime.total_milliseconds () <= 0 ) {
121- backoffTimers_.remove (key);
122- promise.setFailed (ResultTimeout);
123- return ;
124- }
125-
126- DeadlineTimerPtr timerPtr;
127- try {
128- timerPtr = executorProvider_->get ()->createDeadlineTimer ();
129- } catch (const std::runtime_error& e) {
130- LOG_ERROR (" Failed to retry lookup for " << key << " : " << e.what ());
131- promise.setFailed (ResultConnectError);
132- return ;
133- }
134- auto it = backoffTimers_.emplace (key, timerPtr);
135- auto & timer = *(it.first ->second );
136- auto delay = std::min (backoff_.next (), remainingTime);
137- timer.expires_from_now (delay);
138-
139- auto nextRemainingTime = remainingTime - delay;
140- LOG_INFO (" Reschedule " << key << " for " << delay.total_milliseconds ()
141- << " ms, remaining time: " << nextRemainingTime.total_milliseconds ()
142- << " ms" );
143- timer.async_wait ([this , weakSelf, key, f, promise,
144- nextRemainingTime](const boost::system::error_code& ec) {
145- auto self = weakSelf.lock ();
146- if (!self || ec) {
147- if (self && ec != boost::asio::error::operation_aborted) {
148- LOG_ERROR (" The timer for " << key << " failed: " << ec.message ());
149- }
150- // The lookup service has been destructed or the timer has been cancelled
151- promise.setFailed (ResultTimeout);
152- return ;
153- }
154- executeAsyncImpl (key, f, promise, nextRemainingTime);
155- });
156- } else {
157- backoffTimers_.remove (key);
158- promise.setFailed (result);
159- }
160- });
161- }
162-
163- DECLARE_LOG_OBJECT ()
87+ lookupCache_ (RetryableOperationCache<LookupResult>::create(executorProvider, timeoutSeconds)),
88+ partitionLookupCache_(
89+ RetryableOperationCache<LookupDataResultPtr>::create(executorProvider, timeoutSeconds)),
90+ namespaceLookupCache_(
91+ RetryableOperationCache<NamespaceTopicsPtr>::create(executorProvider, timeoutSeconds)),
92+ getSchemaCache_(RetryableOperationCache<SchemaInfo>::create(executorProvider, timeoutSeconds)) {}
16493};
16594
16695} // namespace pulsar
0 commit comments