2626#include < any>
2727#include < atomic>
2828#include < cstdint>
29+ #include < future>
30+ #include < optional>
2931#ifdef USE_ASIO
3032#include < asio/bind_executor.hpp>
3133#include < asio/io_context.hpp>
4244#include < deque>
4345#include < functional>
4446#include < memory>
47+ #include < mutex>
4548#include < string>
4649#include < unordered_map>
50+ #include < utility>
4751#include < vector>
4852
4953#include " AsioTimer.h"
@@ -157,14 +161,9 @@ class PULSAR_PUBLIC ClientConnection : public std::enable_shared_from_this<Clien
157161 * Close the connection.
158162 *
159163 * @param result all pending futures will complete with this result
160- * @param detach remove it from the pool if it's true. When false, the connection remains
161- * associated with the pool but is logically closed; this is currently used when the
162- * pool itself is being closed or when switching clusters.
163164 * @param switchCluster whether the close is triggered by cluster switching
164- *
165- * `detach` should only be false when the connection pool is closed.
166165 */
167- void close (Result result = ResultConnectError, bool detach = true , bool switchCluster = false );
166+ const std::future< void >& close (Result result = ResultConnectError, bool switchCluster = false );
168167
169168 bool isClosed () const ;
170169
@@ -197,7 +196,7 @@ class PULSAR_PUBLIC ClientConnection : public std::enable_shared_from_this<Clien
197196
198197 const std::string& brokerAddress () const ;
199198
200- const std::string& cnxString () const ;
199+ auto cnxString () const { return * std::atomic_load (&cnxStringPtr_); }
201200
202201 int getServerProtocolVersion () const ;
203202
@@ -223,28 +222,48 @@ class PULSAR_PUBLIC ClientConnection : public std::enable_shared_from_this<Clien
223222 mockingRequests_.store (true , std::memory_order_release);
224223 }
225224
226- void handleKeepAliveTimeout ();
225+ void handleKeepAliveTimeout (const ASIO_ERROR & ec );
227226
228227 private:
229228 struct PendingRequestData {
230229 Promise<Result, ResponseData> promise;
231230 DeadlineTimerPtr timer;
232231 std::shared_ptr<std::atomic_bool> hasGotResponse{std::make_shared<std::atomic_bool>(false )};
232+
233+ void fail (Result result) {
234+ cancelTimer (*timer);
235+ promise.setFailed (result);
236+ }
233237 };
234238
235239 struct LookupRequestData {
236240 LookupDataResultPromisePtr promise;
237241 DeadlineTimerPtr timer;
242+
243+ void fail (Result result) {
244+ cancelTimer (*timer);
245+ promise->setFailed (result);
246+ }
238247 };
239248
240249 struct LastMessageIdRequestData {
241250 GetLastMessageIdResponsePromisePtr promise;
242251 DeadlineTimerPtr timer;
252+
253+ void fail (Result result) {
254+ cancelTimer (*timer);
255+ promise->setFailed (result);
256+ }
243257 };
244258
245259 struct GetSchemaRequest {
246260 Promise<Result, SchemaInfo> promise;
247261 DeadlineTimerPtr timer;
262+
263+ void fail (Result result) {
264+ cancelTimer (*timer);
265+ promise.setFailed (result);
266+ }
248267 };
249268
250269 /*
@@ -301,26 +320,26 @@ class PULSAR_PUBLIC ClientConnection : public std::enable_shared_from_this<Clien
301320 }
302321
303322 template <typename ConstBufferSequence, typename WriteHandler>
304- inline void asyncWrite (const ConstBufferSequence& buffers, WriteHandler handler) {
323+ inline void asyncWrite (const ConstBufferSequence& buffers, WriteHandler&& handler) {
305324 if (isClosed ()) {
306325 return ;
307326 }
308327 if (tlsSocket_) {
309- ASIO::async_write (*tlsSocket_, buffers, ASIO::bind_executor (strand_, handler));
328+ ASIO::async_write (*tlsSocket_, buffers, std::forward<WriteHandler>( handler));
310329 } else {
311- ASIO::async_write (*socket_, buffers, handler);
330+ ASIO::async_write (*socket_, buffers, std::forward<WriteHandler>( handler) );
312331 }
313332 }
314333
315334 template <typename MutableBufferSequence, typename ReadHandler>
316- inline void asyncReceive (const MutableBufferSequence& buffers, ReadHandler handler) {
335+ inline void asyncReceive (const MutableBufferSequence& buffers, ReadHandler&& handler) {
317336 if (isClosed ()) {
318337 return ;
319338 }
320339 if (tlsSocket_) {
321- tlsSocket_->async_read_some (buffers, ASIO::bind_executor (strand_, handler));
340+ tlsSocket_->async_read_some (buffers, std::forward<ReadHandler>( handler));
322341 } else {
323- socket_->async_receive (buffers, handler);
342+ socket_->async_receive (buffers, std::forward<ReadHandler>( handler) );
324343 }
325344 }
326345
@@ -341,7 +360,6 @@ class PULSAR_PUBLIC ClientConnection : public std::enable_shared_from_this<Clien
341360 */
342361 SocketPtr socket_;
343362 TlsSocketPtr tlsSocket_;
344- ASIO ::strand<ASIO ::io_context::executor_type> strand_;
345363
346364 const std::string logicalAddress_;
347365 /*
@@ -354,7 +372,7 @@ class PULSAR_PUBLIC ClientConnection : public std::enable_shared_from_this<Clien
354372 ClientConfiguration::ProxyProtocol proxyProtocol_;
355373
356374 // Represent both endpoint of the tcp connection. eg: [client:1234 -> server:6650]
357- std::string cnxString_ ;
375+ std::shared_ptr<std:: string> cnxStringPtr_ ;
358376
359377 /*
360378 * indicates if async connection establishment failed
@@ -364,7 +382,8 @@ class PULSAR_PUBLIC ClientConnection : public std::enable_shared_from_this<Clien
364382 SharedBuffer incomingBuffer_;
365383
366384 Promise<Result, ClientConnectionWeakPtr> connectPromise_;
367- std::shared_ptr<PeriodicTask> connectTimeoutTask_;
385+ const std::chrono::milliseconds connectTimeout_;
386+ const DeadlineTimerPtr connectTimer_;
368387
369388 typedef std::map<long , PendingRequestData> PendingRequestsMap;
370389 PendingRequestsMap pendingRequests_;
@@ -423,6 +442,7 @@ class PULSAR_PUBLIC ClientConnection : public std::enable_shared_from_this<Clien
423442 const std::string clientVersion_;
424443 ConnectionPool& pool_;
425444 const size_t poolIndex_;
445+ std::optional<std::future<void >> closeFuture_;
426446
427447 friend class PulsarFriend ;
428448 friend class ConsumerTest ;
0 commit comments