Fix backend error handling (#586)

Fixes #585
This commit is contained in:
Alex Kremer
2023-04-06 14:21:08 +01:00
committed by GitHub
parent f42e024f38
commit bf65cfabae
5 changed files with 27 additions and 13 deletions

View File

@@ -70,8 +70,15 @@ public:
{ {
if (auto const res = handle_.connect(); not res) if (auto const res = handle_.connect(); not res)
throw std::runtime_error("Could not connect to Cassandra: " + res.error()); throw std::runtime_error("Could not connect to Cassandra: " + res.error());
if (auto const res = handle_.execute(schema_.createKeyspace); not res) if (auto const res = handle_.execute(schema_.createKeyspace); not res)
throw std::runtime_error("Could not create keyspace: " + res.error()); {
// on datastax, creation of keyspaces can be configured to only be done thru the admin interface.
// this does not mean that the keyspace does not already exist tho.
if (res.error().code() != CASS_ERROR_SERVER_UNAUTHORIZED)
throw std::runtime_error("Could not create keyspace: " + res.error());
}
if (auto const res = handle_.executeEach(schema_.createSchema); not res) if (auto const res = handle_.executeEach(schema_.createSchema); not res)
throw std::runtime_error("Could not create schema: " + res.error()); throw std::runtime_error("Could not create schema: " + res.error());

View File

@@ -108,6 +108,7 @@ Cluster::setupContactPoints(Settings::ContactPoints const& points)
}; };
{ {
log_.debug() << "Attempt connection using contact points: " << points.contactPoints;
auto const rc = cass_cluster_set_contact_points(*this, points.contactPoints.data()); auto const rc = cass_cluster_set_contact_points(*this, points.contactPoints.data());
throwErrorIfNeeded(rc, "contact_points", points.contactPoints); throwErrorIfNeeded(rc, "contact_points", points.contactPoints);
} }
@@ -122,6 +123,7 @@ Cluster::setupContactPoints(Settings::ContactPoints const& points)
void void
Cluster::setupSecureBundle(Settings::SecureConnectionBundle const& bundle) Cluster::setupSecureBundle(Settings::SecureConnectionBundle const& bundle)
{ {
log_.debug() << "Attempt connection using secure bundle";
if (auto const rc = cass_cluster_set_cloud_secure_connection_bundle(*this, bundle.bundle.data()); rc != CASS_OK) if (auto const rc = cass_cluster_set_cloud_secure_connection_bundle(*this, bundle.bundle.data()); rc != CASS_OK)
{ {
throw std::runtime_error("Failed to connect using secure connection bundle" + bundle.bundle); throw std::runtime_error("Failed to connect using secure connection bundle" + bundle.bundle);
@@ -134,6 +136,7 @@ Cluster::setupCertificate(Settings const& settings)
if (not settings.certificate) if (not settings.certificate)
return; return;
log_.debug() << "Configure SSL context";
SslContext context = SslContext(*settings.certificate); SslContext context = SslContext(*settings.certificate);
cass_cluster_set_ssl(*this, context); cass_cluster_set_ssl(*this, context);
} }
@@ -144,6 +147,7 @@ Cluster::setupCredentials(Settings const& settings)
if (not settings.username || not settings.password) if (not settings.username || not settings.password)
return; return;
log_.debug() << "Set credentials; username: " << settings.username.value();
cass_cluster_set_credentials(*this, settings.username.value().c_str(), settings.password.value().c_str()); cass_cluster_set_credentials(*this, settings.username.value().c_str(), settings.password.value().c_str());
} }

View File

@@ -20,6 +20,7 @@
#pragma once #pragma once
#include <backend/cassandra/impl/ManagedObject.h> #include <backend/cassandra/impl/ManagedObject.h>
#include <log/Logger.h>
#include <cassandra.h> #include <cassandra.h>
@@ -46,7 +47,7 @@ struct Settings
}; };
bool enableLog = false; bool enableLog = false;
std::chrono::milliseconds connectionTimeout = std::chrono::milliseconds{1000}; std::chrono::milliseconds connectionTimeout = std::chrono::milliseconds{10000};
std::chrono::milliseconds requestTimeout = std::chrono::milliseconds{0}; // no timeout at all std::chrono::milliseconds requestTimeout = std::chrono::milliseconds{0}; // no timeout at all
std::variant<ContactPoints, SecureConnectionBundle> connectionInfo = ContactPoints{}; std::variant<ContactPoints, SecureConnectionBundle> connectionInfo = ContactPoints{};
uint32_t threads = std::thread::hardware_concurrency(); uint32_t threads = std::thread::hardware_concurrency();
@@ -73,6 +74,8 @@ struct Settings
class Cluster : public ManagedObject<CassCluster> class Cluster : public ManagedObject<CassCluster>
{ {
clio::Logger log_{"Backend"};
public: public:
Cluster(Settings const& settings); Cluster(Settings const& settings);

View File

@@ -53,19 +53,19 @@ Future::await() const
ResultOrError ResultOrError
Future::get() const Future::get() const
{ {
if (Result result = cass_future_get_result(*this); not result) if (auto const rc = cass_future_error_code(*this); rc)
{ {
auto [errMsg, code] = [this](std::string label) { auto const errMsg = [this](std::string label) {
char const* message; char const* message;
std::size_t len; std::size_t len;
cass_future_error_message(*this, &message, &len); cass_future_error_message(*this, &message, &len);
return std::make_pair(label + ": " + std::string{message, len}, cass_future_error_code(*this)); return label + ": " + std::string{message, len};
}("future::get()"); }("future::get()");
return Error{CassandraError{errMsg, code}}; return Error{CassandraError{errMsg, rc}};
} }
else else
{ {
return result; return Result{cass_future_get_result(*this)};
} }
} }
@@ -74,19 +74,19 @@ invokeHelper(CassFuture* ptr, void* cbPtr)
{ {
// Note: can't use Future{ptr}.get() because double free will occur :/ // Note: can't use Future{ptr}.get() because double free will occur :/
auto* cb = static_cast<FutureWithCallback::fn_t*>(cbPtr); auto* cb = static_cast<FutureWithCallback::fn_t*>(cbPtr);
if (Result result = cass_future_get_result(ptr); not result) if (auto const rc = cass_future_error_code(ptr); rc)
{ {
auto [errMsg, code] = [&ptr](std::string label) { auto const errMsg = [&ptr](std::string label) {
char const* message; char const* message;
std::size_t len; std::size_t len;
cass_future_error_message(ptr, &message, &len); cass_future_error_message(ptr, &message, &len);
return std::make_pair(label + ": " + std::string{message, len}, cass_future_error_code(ptr)); return label + ": " + std::string{message, len};
}("invokeHelper"); }("invokeHelper");
(*cb)(Error{CassandraError{errMsg, code}}); (*cb)(Error{CassandraError{errMsg, rc}});
} }
else else
{ {
(*cb)(std::move(result)); (*cb)(Result{cass_future_get_result(ptr)});
} }
} }

View File

@@ -48,7 +48,7 @@ TEST_F(SettingsProviderTest, Defaults)
EXPECT_EQ(settings.threads, std::thread::hardware_concurrency()); EXPECT_EQ(settings.threads, std::thread::hardware_concurrency());
EXPECT_EQ(settings.enableLog, false); EXPECT_EQ(settings.enableLog, false);
EXPECT_EQ(settings.connectionTimeout, std::chrono::milliseconds{1000}); EXPECT_EQ(settings.connectionTimeout, std::chrono::milliseconds{10000});
EXPECT_EQ(settings.requestTimeout, std::chrono::milliseconds{0}); EXPECT_EQ(settings.requestTimeout, std::chrono::milliseconds{0});
EXPECT_EQ(settings.certificate, std::nullopt); EXPECT_EQ(settings.certificate, std::nullopt);
EXPECT_EQ(settings.username, std::nullopt); EXPECT_EQ(settings.username, std::nullopt);