Skip to content

Commit

Permalink
enhance framework error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
t-horikawa committed Sep 18, 2024
1 parent b7e1b01 commit e7ac58c
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 19 deletions.
39 changes: 28 additions & 11 deletions src/ogawayama/stub/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,28 +474,45 @@ static inline bool handle_sql_error(ogawayama::stub::tsurugi_error_code& code, :
return false;
}

static inline bool handle_framework_error(ogawayama::stub::tsurugi_error_code& code, ::tateyama::proto::diagnostics::Record& framework_error) {
if (auto itr = ogawayama::transport::framework_error_map.find(framework_error.code()); itr != ogawayama::transport::framework_error_map.end()) {
code.type = tsurugi_error_code::tsurugi_error_type::framework_error;
code.code = itr->second.second;
code.name = itr->second.first;
code.detail = framework_error.message();
return true;
}
return false;
}

/**
* @brief get the error of the last SQL executed
*/
ErrorCode Connection::Impl::tsurugi_error(tsurugi_error_code& code)
{
switch(transport_.last_header().payload_type()) {
case ::tateyama::proto::framework::response::Header_PayloadType::Header_PayloadType_UNKNOWN:
return ErrorCode::UNKNOWN;
break;
case ::tateyama::proto::framework::response::Header_PayloadType::Header_PayloadType_SERVER_DIAGNOSTICS:
code.type = tsurugi_error_code::tsurugi_error_type::framework_error;
return ErrorCode::OK;
case ::tateyama::proto::framework::response::Header_PayloadType::Header_PayloadType_SERVICE_RESULT:
{
auto frame_error = transport_.last_framework_error();
if (handle_framework_error(code, frame_error)) {
return ErrorCode::OK;
}
break;
}

auto sql_error = transport_.last_sql_error();
if (sql_error.code() == ::jogasaki::proto::sql::error::Code::CODE_UNSPECIFIED) {
code.type = tsurugi_error_code::tsurugi_error_type::none;
return ErrorCode::OK;
case ::tateyama::proto::framework::response::Header_PayloadType::Header_PayloadType_SERVICE_RESULT:
{
auto sql_error = transport_.last_sql_error();
if (sql_error.code() == ::jogasaki::proto::sql::error::Code::CODE_UNSPECIFIED) {
code.type = tsurugi_error_code::tsurugi_error_type::none;
return ErrorCode::OK;
}
if (handle_sql_error(code, sql_error)) {
return ErrorCode::OK;
}
break;
}
if (handle_sql_error(code, sql_error)) {
return ErrorCode::OK;
}
return ErrorCode::UNKNOWN;
}
Expand Down
28 changes: 26 additions & 2 deletions src/ogawayama/transport/transport.h
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,9 @@ class transport {
::jogasaki::proto::sql::response::Error& last_sql_error() {
return sql_error_;
}
::tateyama::proto::diagnostics::Record& last_framework_error() {
return framework_error_;
}

private:
tateyama::common::wire::session_wire_container& wire_;
Expand All @@ -365,6 +368,7 @@ class transport {
std::unique_ptr<tateyama::common::wire::timer> timer_{};
::tateyama::proto::framework::response::Header response_header_{};
::jogasaki::proto::sql::response::Error sql_error_{};
::tateyama::proto::diagnostics::Record framework_error_{};

template <typename T>
std::optional<T> send(::jogasaki::proto::sql::request::Request& request, tateyama::common::wire::message_header::index_type& slot_index) {
Expand Down Expand Up @@ -440,8 +444,18 @@ class transport {
if(auto res = tateyama::utils::ParseDelimitedFromZeroCopyStream(std::addressof(response_header_), std::addressof(in), nullptr); ! res) {
return std::nullopt;
}
if (response_header_.payload_type() == ::tateyama::proto::framework::response::Header_PayloadType::Header_PayloadType_SERVER_DIAGNOSTICS) {
std::string_view record{};
if (auto res = tateyama::utils::GetDelimitedBodyFromZeroCopyStream(std::addressof(in), nullptr, record); ! res) {
return std::nullopt;
}
if(auto res = framework_error_.ParseFromArray(record.data(), record.length()); ! res) {
return std::nullopt;
}
throw std::runtime_error("received SERVER_DIAGNOSTICS");
}
if (response_header_.payload_type() != ::tateyama::proto::framework::response::Header_PayloadType::Header_PayloadType_SERVICE_RESULT) {
throw std::runtime_error("SERVER_DIAGNOSTICS");
throw std::runtime_error("unknown payload type");
}
std::string_view payload{};
if (auto res = tateyama::utils::GetDelimitedBodyFromZeroCopyStream(std::addressof(in), nullptr, payload); ! res) {
Expand Down Expand Up @@ -510,8 +524,18 @@ class transport {
if(auto res = tateyama::utils::ParseDelimitedFromZeroCopyStream(std::addressof(response_header_), std::addressof(in), nullptr); ! res) {
return std::nullopt;
}
if (response_header_.payload_type() == ::tateyama::proto::framework::response::Header_PayloadType::Header_PayloadType_SERVER_DIAGNOSTICS) {
std::string_view record{};
if (auto res = tateyama::utils::GetDelimitedBodyFromZeroCopyStream(std::addressof(in), nullptr, record); ! res) {
return std::nullopt;
}
if(auto res = framework_error_.ParseFromArray(record.data(), record.length()); ! res) {
return std::nullopt;
}
throw std::runtime_error("received SERVER_DIAGNOSTICS");
}
if (response_header_.payload_type() != ::tateyama::proto::framework::response::Header_PayloadType::Header_PayloadType_SERVICE_RESULT) {
throw std::runtime_error("SERVER_DIAGNOSTICS");
throw std::runtime_error("unknown payload type");
}
std::string_view response{};
bool eof{};
Expand Down
40 changes: 40 additions & 0 deletions src/ogawayama/transport/tsurugi_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,5 +149,45 @@ static const std::map<::jogasaki::proto::sql::error::Code, std::pair<std::string
{::jogasaki::proto::sql::error::Code::BLOCKED_BY_CONCURRENT_OPERATION_EXCEPTION, {"BLOCKED_BY_CONCURRENT_OPERATION_EXCEPTION", 4007}}
};

static const std::map<::tateyama::proto::diagnostics::Code, std::pair<std::string, std::int64_t>> framework_error_map = { // NOLINT

{::tateyama::proto::diagnostics::Code::UNKNOWN, {"unknown error was occurred in the server.", 0}},

{::tateyama::proto::diagnostics::Code::SYSTEM_ERROR, {"the server system is something wrong.", 100}},

{::tateyama::proto::diagnostics::Code::UNSUPPORTED_OPERATION, {"the requested operation is not supported.", 101}},

{::tateyama::proto::diagnostics::Code::ILLEGAL_STATE, {"I/O error was occurred in the server.", 102}},

{::tateyama::proto::diagnostics::Code::ILLEGAL_STATE, {"operation was requested in illegal or inappropriate time.", 102}},

{::tateyama::proto::diagnostics::Code::IO_ERROR, {"I/O error was occurred in the server.", 103}},

{::tateyama::proto::diagnostics::Code::OUT_OF_MEMORY, {"the server is out of memory.", 104}},

{::tateyama::proto::diagnostics::Code::RESOURCE_LIMIT_REACHED, {"the server reached resource limit.", 105}},

{::tateyama::proto::diagnostics::Code::AUTHENTICATION_ERROR, {"authentication was failed.", 201}},

{::tateyama::proto::diagnostics::Code::PERMISSION_ERROR, {"request is not permitted.", 202}},

{::tateyama::proto::diagnostics::Code::ACCESS_EXPIRED, {"access right has been expired.", 203}},

{::tateyama::proto::diagnostics::Code::REFRESH_EXPIRED, {"refresh right has been expired.", 204}},

{::tateyama::proto::diagnostics::Code::BROKEN_CREDENTIAL, {"credential information is broken.", 205}},

{::tateyama::proto::diagnostics::Code::SESSION_CLOSED, {"the current session is already closed.", 301}},

{::tateyama::proto::diagnostics::Code::SESSION_EXPIRED, {"the current session is expired.", 302}},

{::tateyama::proto::diagnostics::Code::SERVICE_NOT_FOUND, {"the destination service was not found.", 401}},

{::tateyama::proto::diagnostics::Code::SERVICE_UNAVAILABLE, {"the destination service was not found.", 402}},

{::tateyama::proto::diagnostics::Code::OPERATION_CANCELED, {"operation was canceled by user or system.", 403}},

{::tateyama::proto::diagnostics::Code::INVALID_REQUEST, {"the service received a request message with invalid payload.", 501}}
};

} // namespace ogawayama::transport
2 changes: 2 additions & 0 deletions test/ogawayama/stub/ErrorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,8 @@ TEST_F(ErrorTest, framework) {
ogawayama::stub::tsurugi_error_code code{};
EXPECT_EQ(ERROR_CODE::OK, connection->tsurugi_error(code));
EXPECT_EQ(code.type, ogawayama::stub::tsurugi_error_code::tsurugi_error_type::framework_error);
EXPECT_EQ(code.code, 403); // SCD-00403 is OPERATION_CANCELED
EXPECT_EQ(code.name, "operation was canceled by user or system.");
}
}

Expand Down
11 changes: 5 additions & 6 deletions test/ogawayama/stub/endpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,11 @@ class endpoint {
if(auto res = tateyama::utils::SerializeDelimitedToOstream(endpoint_->framework_header_, std::addressof(ss)); ! res) {
throw std::runtime_error("error formatting response message");
}
std::ostringstream ofs;
boost::archive::binary_oarchive oa(ofs);
oa << ERROR_CODE::OK;
std::string code = ofs.str();
if(auto res = tateyama::utils::PutDelimitedBodyToOstream(code, std::addressof(ss)); ! res) {
throw std::runtime_error("error formatting response message");
::tateyama::proto::diagnostics::Record r{};
r.set_code(::tateyama::proto::diagnostics::Code::OPERATION_CANCELED);
auto record = r.SerializeAsString();
if(auto res = tateyama::utils::PutDelimitedBodyToOstream(record, std::addressof(ss)); ! res) {
throw std::runtime_error("error formatting record message");
}
auto reply_message = ss.str();
wire_->get_response_wire().write(reply_message.data(), tateyama::common::wire::response_header(index, reply_message.length(), RESPONSE_BODY));
Expand Down

1 comment on commit e7ac58c

@t-horikawa
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.