Add bolt verbose error

Reviewers: msantl

Reviewed By: msantl

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1948
This commit is contained in:
Matej Ferencevic 2019-04-11 10:02:12 +02:00
parent c269e2f468
commit 4029026c3b
4 changed files with 90 additions and 17 deletions

View File

@ -0,0 +1,78 @@
/// @file
#pragma once
#include <fmt/format.h>
#include "utils/exceptions.hpp"
namespace communication::bolt {
/**
* Used to indicate something is wrong with the client but the transaction is
* kept open for a potential retry.
*
* The most common use case for throwing this error is if something is wrong
* with the query. Perhaps a simple syntax error that can be fixed and query
* retried.
*/
class ClientError : public utils::BasicException {
public:
using utils::BasicException::BasicException;
};
/**
* All exceptions that are sent to the client consist of two parts. The first
* part is `code` it specifies the type of exception that was raised. The second
* part is `message` which is a pretty error message that can be displayed to a
* human.
*
* The first part is more interesting for machine processing. It should have the
* following format: `Memgraph.[Classification].[Category].[Title]` It is
* defined here: https://neo4j.com/docs/status-codes/current/
*
* The first part of the `code` is always Memgraph, it indicates the database.
* The second part is `classification`. The `classification` part is specified
* by Neo to always be one of "ClientError", "ClientNotification",
* "TransientError" or "DatabaseError". We won't use "ClientNotification".
*
* The `category` and `title` parts can be freely specified.
*/
class VerboseError : public utils::BasicException {
public:
enum class Classification {
// Client and Database errors mean that the client shouldn't retry the
// query.
CLIENT_ERROR,
DATABASE_ERROR,
// Transient error means that the client should retry the query.
TRANSIENT_ERROR,
};
template <class... Args>
VerboseError(Classification classification, const std::string &category,
const std::string &title, const std::string &format,
Args &&... args)
: BasicException(format, std::forward<Args>(args)...),
code_(fmt::format("Memgraph.{}.{}.{}",
ClassificationToString(classification), category,
title)) {}
const std::string &code() const noexcept { return code_; }
private:
std::string ClassificationToString(Classification classification) {
switch (classification) {
case Classification::CLIENT_ERROR:
return "ClientError";
case Classification::DATABASE_ERROR:
return "DatabaseError";
case Classification::TRANSIENT_ERROR:
return "TransientError";
}
}
std::string code_;
};
} // namespace communication::bolt

View File

@ -7,28 +7,18 @@
#include <glog/logging.h>
#include "communication/bolt/v1/codes.hpp"
#include "communication/bolt/v1/exceptions.hpp"
#include "communication/bolt/v1/state.hpp"
#include "communication/bolt/v1/value.hpp"
#include "utils/exceptions.hpp"
namespace communication::bolt {
/**
* Used to indicate something is wrong with the client but the transaction is
* kept open for a potential retry.
*
* The most common use case for throwing this error is if something is wrong
* with the query. Perhaps a simple syntax error that can be fixed and query
* retried.
*/
class ClientError : public utils::BasicException {
public:
using utils::BasicException::BasicException;
};
// TODO (mferencevic): revise these error messages
inline std::pair<std::string, std::string> ExceptionToErrorMessage(
const std::exception &e) {
if (auto *verbose = dynamic_cast<const VerboseError *>(&e)) {
return {verbose->code(), verbose->what()};
}
if (dynamic_cast<const ClientError *>(&e)) {
// Clients expect 4 strings separated by dots. First being database name
// (for example: Neo, Memgraph...), second being either ClientError,

View File

@ -11,6 +11,7 @@
#include "audit/log.hpp"
#include "auth/auth.hpp"
#include "communication/bolt/v1/exceptions.hpp"
#include "communication/bolt/v1/session.hpp"
#include "communication/init.hpp"
#include "communication/session.hpp"

View File

@ -2,15 +2,19 @@
#pragma once
#include "utils/exceptions.hpp"
#include "communication/bolt/v1/exceptions.hpp"
namespace raft {
/// Base exception class used for all exceptions that can occur within the
/// Raft protocol.
class RaftException : public utils::BasicException {
class RaftException : public communication::bolt::VerboseError {
public:
using utils::BasicException::BasicException;
template <class... Args>
RaftException(const std::string &format, Args &&... args)
: communication::bolt::VerboseError(
communication::bolt::VerboseError::Classification::DATABASE_ERROR,
"Raft", "Error", format, std::forward<Args>(args)...) {}
};
/// This exception should be thrown when attempting to transition between