Skip to content

Commit ece5e9b

Browse files
committed
Better fix + updated tests
1 parent b4fe02f commit ece5e9b

File tree

2 files changed

+44
-21
lines changed

2 files changed

+44
-21
lines changed

clickhouse/client.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -385,15 +385,17 @@ void Client::Impl::ResetConnectionEndpoint() {
385385
}
386386

387387
void Client::Impl::CreateConnection() {
388-
// i <= 1 to try at least once
389-
for (size_t i = 0; i <= 1 || i < options_.send_retries;)
388+
// make sure to try to connect to each endpoint at least once even if `options_.send_retries` is 0
389+
const size_t max_attempts = (options_.send_retries ? options_.send_retries : 1);
390+
for (size_t i = 0; i < max_attempts;)
390391
{
391392
try
392393
{
394+
// Try to connect to each endpoint before throwing exception.
393395
ResetConnectionEndpoint();
394396
return;
395397
} catch (const std::system_error&) {
396-
if (++i >= options_.send_retries)
398+
if (++i >= max_attempts)
397399
{
398400
throw;
399401
}

ut/client_ut.cpp

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,58 +1369,79 @@ INSTANTIATE_TEST_SUITE_P(ResetConnectionClientTest, ResetConnectionTestCase,
13691369
));
13701370

13711371
struct CountingSocketFactoryAdapter : public SocketFactory {
1372-
struct Counters
1373-
{
1374-
size_t connect_count = 0;
13751372

1376-
void Reset() {
1377-
*this = Counters();
1378-
}
1379-
};
1373+
using ConnectRequests = std::vector<std::pair<ClientOptions, Endpoint>>;
13801374

13811375
SocketFactory & socket_factory;
1382-
Counters& counters;
1376+
ConnectRequests & connect_requests;
13831377

1384-
CountingSocketFactoryAdapter(SocketFactory & socket_factory, Counters& counters)
1378+
CountingSocketFactoryAdapter(SocketFactory & socket_factory, ConnectRequests& connect_requests)
13851379
: socket_factory(socket_factory)
1386-
, counters(counters)
1380+
, connect_requests(connect_requests)
13871381
{}
13881382

13891383
std::unique_ptr<SocketBase> connect(const ClientOptions& opts, const Endpoint& endpoint) {
1390-
++counters.connect_count;
1384+
connect_requests.emplace_back(opts, endpoint);
1385+
13911386
return socket_factory.connect(opts, endpoint);
13921387
}
13931388

13941389
void sleepFor(const std::chrono::milliseconds& duration) {
13951390
return socket_factory.sleepFor(duration);
13961391
}
13971392

1393+
size_t GetConnectRequestsCount() const {
1394+
return connect_requests.size();
1395+
}
1396+
13981397
};
13991398

14001399
TEST(SimpleClientTest, issue_335) {
1400+
// Make sure Client connects to server even with ClientOptions.SetSendRetries(0)
14011401
auto vals = MakeStrings();
14021402
auto col = std::make_shared<ColumnString>(vals);
14031403

1404-
CountingSocketFactoryAdapter::Counters counters;
1404+
CountingSocketFactoryAdapter::ConnectRequests connect_requests;
14051405
std::unique_ptr<SocketFactory> wrapped_socket_factory = std::make_unique<NonSecureSocketFactory>();
1406-
std::unique_ptr<SocketFactory> socket_factory = std::make_unique<CountingSocketFactoryAdapter>(*wrapped_socket_factory, counters);
1406+
std::unique_ptr<SocketFactory> socket_factory = std::make_unique<CountingSocketFactoryAdapter>(*wrapped_socket_factory, connect_requests);
14071407

14081408
Client client(ClientOptions(LocalHostEndpoint)
14091409
.SetSendRetries(0), // <<=== crucial for reproducing https://github.com/ClickHouse/clickhouse-cpp/issues/335
14101410
std::move(socket_factory));
14111411

1412-
EXPECT_EQ(1u, counters.connect_count);
1412+
EXPECT_EQ(1u, connect_requests.size());
14131413
EXPECT_TRUE(CompareRecursive(vals, *RoundtripColumnValuesTyped(client, col)));
14141414

1415-
counters.Reset();
1415+
connect_requests.clear();
14161416

14171417
client.ResetConnection();
1418-
EXPECT_EQ(1u, counters.connect_count);
1418+
EXPECT_EQ(1u, connect_requests.size());
14191419
EXPECT_TRUE(CompareRecursive(vals, *RoundtripColumnValuesTyped(client, col)));
14201420

1421-
counters.Reset();
1421+
connect_requests.clear();
14221422

14231423
client.ResetConnectionEndpoint();
1424-
EXPECT_EQ(1u, counters.connect_count);
1424+
EXPECT_EQ(1u, connect_requests.size());
14251425
EXPECT_TRUE(CompareRecursive(vals, *RoundtripColumnValuesTyped(client, col)));
14261426
}
1427+
1428+
TEST(SimpleClientTest, issue_335_reconnects_count) {
1429+
// Make sure that client attempts to connect to each endpoint at least once.
1430+
CountingSocketFactoryAdapter::ConnectRequests connect_requests;
1431+
std::unique_ptr<SocketFactory> wrapped_socket_factory = std::make_unique<NonSecureSocketFactory>();
1432+
std::unique_ptr<SocketFactory> socket_factory = std::make_unique<CountingSocketFactoryAdapter>(*wrapped_socket_factory, connect_requests);
1433+
1434+
const auto endpoints = {
1435+
Endpoint{"foo-invalid-hostname", 1234},
1436+
Endpoint{"bar-invalid-hostname", 4567},
1437+
};
1438+
1439+
EXPECT_ANY_THROW(
1440+
Client(ClientOptions()
1441+
.SetEndpoints(endpoints)
1442+
.SetSendRetries(0), // <<=== crucial for reproducing https://github.com/ClickHouse/clickhouse-cpp/issues/335
1443+
std::move(socket_factory));
1444+
);
1445+
1446+
EXPECT_EQ(endpoints.size(), connect_requests.size());
1447+
}

0 commit comments

Comments
 (0)