Files
scylladb/replica/exceptions.hh
Piotr Dulikowski 621b7f35e2 replica: add rate_limit_exception and a simple serialization framework
Introduces `replica::rate_limit_exception` - an exceptions that is
supposed to be thrown/returned on the replica side when the request is
rejected due to the exceeding the per-partition rate limit.

Additionally, introduces the `exception_variant` type which allows to
transport the new exception over RPC while preserving the type
information. This will be useful in later commits, as the coordinator
will have to know whether a replica has failed due to rate limit being
exceeded or another kind of error.

The `exception_variant` currently can only either hold "other exception"
(std::monostate) or the aforementioned `rate_limit_exception`, but can
be extended in a backwards-compatible way in the future to be able to
hold more exceptions that need to be handled in a different way.
2022-06-22 20:07:58 +02:00

74 lines
1.7 KiB
C++

/*
* Copyright 2022-present ScyllaDB
*/
/*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#pragma once
#include <cstdint>
#include <exception>
#include <optional>
#include <variant>
#include "seastar/core/sstring.hh"
#include "seastar/core/timed_out_error.hh"
#include "utils/exception_container.hh"
#include "utils/result.hh"
namespace replica {
// A marker indicating that the exception_variant holds an unknown exception.
// For example, replica sends a new type of error and coordinator does not
// understand it because it wasn't upgraded to a newer version yet.
struct unknown_exception {};
// A marker indicating that the exception variant doesn't hold any exception.
struct no_exception {};
class replica_exception : public std::exception {
public:
replica_exception() noexcept {};
};
class rate_limit_exception final : public replica_exception {
public:
rate_limit_exception() noexcept
: replica_exception()
{ }
virtual const char* what() const noexcept override { return "rate limit exceeded"; }
};
struct exception_variant {
std::variant<unknown_exception,
no_exception,
rate_limit_exception
> reason;
exception_variant()
: reason(no_exception{})
{ }
template<typename Ex>
exception_variant(Ex&& ex)
: reason(std::move(ex))
{ }
std::exception_ptr into_exception_ptr() noexcept;
inline operator bool() const noexcept {
return !std::holds_alternative<no_exception>(reason);
}
};
// Tries to encode the exception into an exception_variant.
// If given exception cannot be encoded into one of the replica exception types,
// returns no_exception.
exception_variant try_encode_replica_exception(std::exception_ptr eptr);
}