mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-20 03:35:55 +00:00
feat: Cache state endpoint (#2642)
This commit is contained in:
@@ -189,6 +189,7 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
|
||||
httpServer->onGet("/metrics", MetricsHandler{adminVerifier});
|
||||
httpServer->onGet("/health", HealthCheckHandler{});
|
||||
httpServer->onGet("/cache_state", CacheStateHandler{cache});
|
||||
auto requestHandler = RequestHandler{adminVerifier, handler};
|
||||
httpServer->onPost("/", requestHandler);
|
||||
httpServer->onWs(std::move(requestHandler));
|
||||
@@ -214,7 +215,7 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
// Init the web server
|
||||
auto handler = std::make_shared<web::RPCServerHandler<RPCEngineType>>(config_, backend, rpcEngine, etl, dosGuard);
|
||||
|
||||
auto const httpServer = web::makeHttpServer(config_, ioc, dosGuard, handler);
|
||||
auto const httpServer = web::makeHttpServer(config_, ioc, dosGuard, handler, cache);
|
||||
|
||||
// Blocks until stopped.
|
||||
// When stopped, shared_ptrs fall out of scope
|
||||
|
||||
@@ -120,4 +120,34 @@ HealthCheckHandler::operator()(
|
||||
return web::ng::Response{boost::beast::http::status::ok, kHEALTH_CHECK_HTML, request};
|
||||
}
|
||||
|
||||
web::ng::Response
|
||||
CacheStateHandler::operator()(
|
||||
web::ng::Request const& request,
|
||||
web::ng::ConnectionMetadata&,
|
||||
web::SubscriptionContextPtr,
|
||||
boost::asio::yield_context
|
||||
)
|
||||
{
|
||||
static constexpr auto kCACHE_CHECK_LOADED_HTML = R"html(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Cache state</title></head>
|
||||
<body><h1>Cache state</h1><p>Cache is fully loaded</p></body>
|
||||
</html>
|
||||
)html";
|
||||
|
||||
static constexpr auto kCACHE_CHECK_NOT_LOADED_HTML = R"html(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Cache state</title></head>
|
||||
<body><h1>Cache state</h1><p>Cache is not yet loaded</p></body>
|
||||
</html>
|
||||
)html";
|
||||
|
||||
if (cache_.get().isFull())
|
||||
return web::ng::Response{boost::beast::http::status::ok, kCACHE_CHECK_LOADED_HTML, request};
|
||||
|
||||
return web::ng::Response{boost::beast::http::status::service_unavailable, kCACHE_CHECK_NOT_LOADED_HTML, request};
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data/LedgerCacheInterface.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
#include "web/AdminVerificationStrategy.hpp"
|
||||
@@ -163,6 +164,37 @@ public:
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A function object that handles the cache state check endpoint.
|
||||
*/
|
||||
class CacheStateHandler {
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new CacheStateHandler object.
|
||||
*
|
||||
* @param cache The ledger cache to use.
|
||||
*/
|
||||
CacheStateHandler(data::LedgerCacheInterface const& cache) : cache_{cache}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The call of the function object.
|
||||
*
|
||||
* @param request The request to handle.
|
||||
* @return The response to the request
|
||||
*/
|
||||
web::ng::Response
|
||||
operator()(
|
||||
web::ng::Request const& request,
|
||||
web::ng::ConnectionMetadata&,
|
||||
web::SubscriptionContextPtr,
|
||||
boost::asio::yield_context
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A function object that handles the websocket endpoint.
|
||||
*
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data/LedgerCacheInterface.hpp"
|
||||
#include "util/Taggable.hpp"
|
||||
#include "web/AdminVerificationStrategy.hpp"
|
||||
#include "web/PlainWsSession.hpp"
|
||||
@@ -69,6 +70,7 @@ public:
|
||||
* @param tagFactory A factory that is used to generate tags to track requests and sessions
|
||||
* @param dosGuard The denial of service guard to use
|
||||
* @param handler The server handler to use
|
||||
* @param cache The ledger cache to use
|
||||
* @param buffer Buffer with initial data received from the peer
|
||||
* @param maxWsSendingQueueSize The maximum size of the sending queue for websocket
|
||||
*/
|
||||
@@ -80,6 +82,7 @@ public:
|
||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||
std::shared_ptr<HandlerType> const& handler,
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache,
|
||||
boost::beast::flat_buffer buffer,
|
||||
std::uint32_t maxWsSendingQueueSize
|
||||
)
|
||||
@@ -90,6 +93,7 @@ public:
|
||||
std::move(proxyIpResolver),
|
||||
dosGuard,
|
||||
handler,
|
||||
cache,
|
||||
std::move(buffer)
|
||||
)
|
||||
, stream_(std::move(socket))
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data/LedgerCacheInterface.hpp"
|
||||
#include "util/Taggable.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
#include "web/AdminVerificationStrategy.hpp"
|
||||
@@ -85,6 +86,7 @@ class Detector : public std::enable_shared_from_this<Detector<PlainSessionType,
|
||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory_;
|
||||
std::reference_wrapper<dosguard::DOSGuardInterface> const dosGuard_;
|
||||
std::shared_ptr<HandlerType> const handler_;
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache_;
|
||||
boost::beast::flat_buffer buffer_;
|
||||
std::shared_ptr<AdminVerificationStrategy> const adminVerification_;
|
||||
std::uint32_t maxWsSendingQueueSize_;
|
||||
@@ -99,6 +101,7 @@ public:
|
||||
* @param tagFactory A factory that is used to generate tags to track requests and sessions
|
||||
* @param dosGuard The denial of service guard to use
|
||||
* @param handler The server handler to use
|
||||
* @param cache The ledger cache to use
|
||||
* @param adminVerification The admin verification strategy to use
|
||||
* @param maxWsSendingQueueSize The maximum size of the sending queue for websocket
|
||||
* @param proxyIpResolver The client ip resolver if a request was forwarded by a proxy
|
||||
@@ -109,6 +112,7 @@ public:
|
||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||
std::shared_ptr<HandlerType> handler,
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache,
|
||||
std::shared_ptr<AdminVerificationStrategy> adminVerification,
|
||||
std::uint32_t maxWsSendingQueueSize,
|
||||
std::shared_ptr<ProxyIpResolver> proxyIpResolver
|
||||
@@ -118,6 +122,7 @@ public:
|
||||
, tagFactory_(std::cref(tagFactory))
|
||||
, dosGuard_(dosGuard)
|
||||
, handler_(std::move(handler))
|
||||
, cache_(cache)
|
||||
, adminVerification_(std::move(adminVerification))
|
||||
, maxWsSendingQueueSize_(maxWsSendingQueueSize)
|
||||
, proxyIpResolver_(std::move(proxyIpResolver))
|
||||
@@ -179,6 +184,7 @@ public:
|
||||
tagFactory_,
|
||||
dosGuard_,
|
||||
handler_,
|
||||
cache_,
|
||||
std::move(buffer_),
|
||||
maxWsSendingQueueSize_
|
||||
)
|
||||
@@ -194,6 +200,7 @@ public:
|
||||
tagFactory_,
|
||||
dosGuard_,
|
||||
handler_,
|
||||
cache_,
|
||||
std::move(buffer_),
|
||||
maxWsSendingQueueSize_
|
||||
)
|
||||
@@ -223,6 +230,7 @@ class Server : public std::enable_shared_from_this<Server<PlainSessionType, SslS
|
||||
util::TagDecoratorFactory tagFactory_;
|
||||
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard_;
|
||||
std::shared_ptr<HandlerType> handler_;
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache_;
|
||||
tcp::acceptor acceptor_;
|
||||
std::shared_ptr<AdminVerificationStrategy> adminVerification_;
|
||||
std::uint32_t maxWsSendingQueueSize_;
|
||||
@@ -238,6 +246,7 @@ public:
|
||||
* @param tagFactory A factory that is used to generate tags to track requests and sessions
|
||||
* @param dosGuard The denial of service guard to use
|
||||
* @param handler The server handler to use
|
||||
* @param cache The ledger cache to use
|
||||
* @param adminVerification The admin verification strategy to use
|
||||
* @param maxWsSendingQueueSize The maximum size of the sending queue for websocket
|
||||
* @param proxyIpResolver The client ip resolver if a request was forwarded by a proxy
|
||||
@@ -249,6 +258,7 @@ public:
|
||||
util::TagDecoratorFactory tagFactory,
|
||||
dosguard::DOSGuardInterface& dosGuard,
|
||||
std::shared_ptr<HandlerType> handler,
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache,
|
||||
std::shared_ptr<AdminVerificationStrategy> adminVerification,
|
||||
std::uint32_t maxWsSendingQueueSize,
|
||||
ProxyIpResolver proxyIpResolver
|
||||
@@ -258,6 +268,7 @@ public:
|
||||
, tagFactory_(tagFactory)
|
||||
, dosGuard_(std::ref(dosGuard))
|
||||
, handler_(std::move(handler))
|
||||
, cache_(cache)
|
||||
, acceptor_(boost::asio::make_strand(ioc))
|
||||
, adminVerification_(std::move(adminVerification))
|
||||
, maxWsSendingQueueSize_(maxWsSendingQueueSize)
|
||||
@@ -320,6 +331,7 @@ private:
|
||||
std::cref(tagFactory_),
|
||||
dosGuard_,
|
||||
handler_,
|
||||
cache_,
|
||||
adminVerification_,
|
||||
maxWsSendingQueueSize_,
|
||||
proxyIpResolver_
|
||||
@@ -343,6 +355,7 @@ using HttpServer = Server<HttpSession, SslHttpSession, HandlerType>;
|
||||
* @param ioc The server will run under this io_context
|
||||
* @param dosGuard The dos guard to protect the server
|
||||
* @param handler The handler to process the request
|
||||
* @param cache The ledger cache to use
|
||||
* @return The server instance
|
||||
*/
|
||||
template <typename HandlerType>
|
||||
@@ -351,7 +364,8 @@ makeHttpServer(
|
||||
util::config::ClioConfigDefinition const& config,
|
||||
boost::asio::io_context& ioc,
|
||||
dosguard::DOSGuardInterface& dosGuard,
|
||||
std::shared_ptr<HandlerType> const& handler
|
||||
std::shared_ptr<HandlerType> const& handler,
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache
|
||||
)
|
||||
{
|
||||
static util::Logger const log{"WebServer"}; // NOLINT(readability-identifier-naming)
|
||||
@@ -385,6 +399,7 @@ makeHttpServer(
|
||||
util::TagDecoratorFactory(config),
|
||||
dosGuard,
|
||||
handler,
|
||||
cache,
|
||||
std::move(expectedAdminVerification).value(),
|
||||
maxWsSendingQueueSize,
|
||||
std::move(proxyIpResolver)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data/LedgerCacheInterface.hpp"
|
||||
#include "util/Taggable.hpp"
|
||||
#include "web/AdminVerificationStrategy.hpp"
|
||||
#include "web/ProxyIpResolver.hpp"
|
||||
@@ -76,6 +77,7 @@ public:
|
||||
* @param tagFactory A factory that is used to generate tags to track requests and sessions
|
||||
* @param dosGuard The denial of service guard to use
|
||||
* @param handler The server handler to use
|
||||
* @param cache The ledger cache to use
|
||||
* @param buffer Buffer with initial data received from the peer
|
||||
* @param maxWsSendingQueueSize The maximum size of the sending queue for websocket
|
||||
*/
|
||||
@@ -88,6 +90,7 @@ public:
|
||||
std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
|
||||
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||
std::shared_ptr<HandlerType> const& handler,
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache,
|
||||
boost::beast::flat_buffer buffer,
|
||||
std::uint32_t maxWsSendingQueueSize
|
||||
)
|
||||
@@ -98,6 +101,7 @@ public:
|
||||
std::move(proxyIpResolver),
|
||||
dosGuard,
|
||||
handler,
|
||||
cache,
|
||||
std::move(buffer)
|
||||
)
|
||||
, stream_(std::move(socket), ctx)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data/LedgerCacheInterface.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/Taggable.hpp"
|
||||
@@ -71,6 +72,22 @@ static constexpr auto kHEALTH_CHECK_HTML = R"html(
|
||||
</html>
|
||||
)html";
|
||||
|
||||
static constexpr auto kCACHE_CHECK_LOADED_HTML = R"html(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Cache state</title></head>
|
||||
<body><h1>Cache state</h1><p>Cache is fully loaded</p></body>
|
||||
</html>
|
||||
)html";
|
||||
|
||||
static constexpr auto kCACHE_CHECK_NOT_LOADED_HTML = R"html(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Cache state</title></head>
|
||||
<body><h1>Cache state</h1><p>Cache is not yet loaded</p></body>
|
||||
</html>
|
||||
)html";
|
||||
|
||||
using tcp = boost::asio::ip::tcp;
|
||||
|
||||
/**
|
||||
@@ -128,6 +145,7 @@ protected:
|
||||
http::request<http::string_body> req_;
|
||||
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard_;
|
||||
std::shared_ptr<HandlerType> const handler_;
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache_;
|
||||
util::Logger log_{"WebServer"};
|
||||
util::Logger perfLog_{"Performance"};
|
||||
|
||||
@@ -169,6 +187,7 @@ public:
|
||||
std::shared_ptr<ProxyIpResolver> proxyIpResolver,
|
||||
std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
|
||||
std::shared_ptr<HandlerType> handler,
|
||||
std::reference_wrapper<data::LedgerCacheInterface const> cache,
|
||||
boost::beast::flat_buffer buffer
|
||||
)
|
||||
: ConnectionBase(tagFactory, ip)
|
||||
@@ -178,6 +197,7 @@ public:
|
||||
, buffer_(std::move(buffer))
|
||||
, dosGuard_(dosGuard)
|
||||
, handler_(std::move(handler))
|
||||
, cache_(cache)
|
||||
{
|
||||
LOG(perfLog_.debug()) << tag() << "http session created";
|
||||
dosGuard_.get().increment(ip);
|
||||
@@ -222,6 +242,13 @@ public:
|
||||
if (req_.method() == http::verb::get and req_.target() == "/health")
|
||||
return sender_(httpResponse(http::status::ok, "text/html", kHEALTH_CHECK_HTML));
|
||||
|
||||
if (req_.method() == http::verb::get and req_.target() == "/cache_state") {
|
||||
if (cache_.get().isFull())
|
||||
return sender_(httpResponse(http::status::ok, "text/html", kCACHE_CHECK_LOADED_HTML));
|
||||
|
||||
return sender_(httpResponse(http::status::service_unavailable, "text/html", kCACHE_CHECK_NOT_LOADED_HTML));
|
||||
}
|
||||
|
||||
if (auto resolvedIp = proxyIpResolver_->resolveClientIp(clientIp_, req_); resolvedIp != clientIp_) {
|
||||
LOG(log_.info()) << tag() << "Detected a forwarded request from proxy. Proxy ip: " << clientIp_
|
||||
<< ". Resolved client ip: " << resolvedIp;
|
||||
|
||||
Reference in New Issue
Block a user