Skip to content

Commit 1b1a46c

Browse files
authored
feat: Handle prometheus requests in WorkQueue (#2790)
1 parent 89707d9 commit 1b1a46c

File tree

4 files changed

+53
-16
lines changed

4 files changed

+53
-16
lines changed

src/app/ClioApplication.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ ClioApplication::run(bool const useNgWebServer)
182182
return EXIT_FAILURE;
183183
}
184184

185-
httpServer->onGet("/metrics", MetricsHandler{adminVerifier});
185+
httpServer->onGet("/metrics", MetricsHandler{adminVerifier, workQueue});
186186
httpServer->onGet("/health", HealthCheckHandler{});
187187
httpServer->onGet("/cache_state", CacheStateHandler{cache});
188188
auto requestHandler = RequestHandler{adminVerifier, handler};

src/app/WebHandlers.cpp

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919

2020
#include "app/WebHandlers.hpp"
2121

22+
#include "rpc/Errors.hpp"
23+
#include "rpc/WorkQueue.hpp"
2224
#include "util/Assert.hpp"
25+
#include "util/CoroutineGroup.hpp"
2326
#include "util/prometheus/Http.hpp"
2427
#include "web/AdminVerificationStrategy.hpp"
2528
#include "web/SubscriptionContextInterface.hpp"
@@ -31,6 +34,7 @@
3134
#include <boost/asio/spawn.hpp>
3235
#include <boost/beast/http/status.hpp>
3336

37+
#include <functional>
3438
#include <memory>
3539
#include <optional>
3640
#include <string>
@@ -76,8 +80,8 @@ DisconnectHook::operator()(web::ng::Connection const& connection)
7680
dosguard_.get().decrement(connection.ip());
7781
}
7882

79-
MetricsHandler::MetricsHandler(std::shared_ptr<web::AdminVerificationStrategy> adminVerifier)
80-
: adminVerifier_{std::move(adminVerifier)}
83+
MetricsHandler::MetricsHandler(std::shared_ptr<web::AdminVerificationStrategy> adminVerifier, rpc::WorkQueue& workQueue)
84+
: adminVerifier_{std::move(adminVerifier)}, workQueue_{std::ref(workQueue)}
8185
{
8286
}
8387

@@ -86,19 +90,45 @@ MetricsHandler::operator()(
8690
web::ng::Request const& request,
8791
web::ng::ConnectionMetadata& connectionMetadata,
8892
web::SubscriptionContextPtr,
89-
boost::asio::yield_context
93+
boost::asio::yield_context yield
9094
)
9195
{
92-
auto const maybeHttpRequest = request.asHttpRequest();
93-
ASSERT(maybeHttpRequest.has_value(), "Got not a http request in Get");
94-
auto const& httpRequest = maybeHttpRequest->get();
95-
96-
// FIXME(#1702): Using veb server thread to handle prometheus request. Better to post on work queue.
97-
auto maybeResponse = util::prometheus::handlePrometheusRequest(
98-
httpRequest, adminVerifier_->isAdmin(httpRequest, connectionMetadata.ip())
96+
std::optional<web::ng::Response> response;
97+
util::CoroutineGroup coroutineGroup{yield, 1};
98+
auto const onTaskComplete = coroutineGroup.registerForeign(yield);
99+
ASSERT(onTaskComplete.has_value(), "Coroutine group can't be full");
100+
101+
bool const postSuccessful = workQueue_.get().postCoro(
102+
[this, &request, &response, &onTaskComplete = onTaskComplete.value(), &connectionMetadata](
103+
boost::asio::yield_context
104+
) mutable {
105+
auto const maybeHttpRequest = request.asHttpRequest();
106+
ASSERT(maybeHttpRequest.has_value(), "Got not a http request in Get");
107+
auto const& httpRequest = maybeHttpRequest->get();
108+
109+
auto maybeResponse = util::prometheus::handlePrometheusRequest(
110+
httpRequest, adminVerifier_->isAdmin(httpRequest, connectionMetadata.ip())
111+
);
112+
ASSERT(maybeResponse.has_value(), "Got unexpected request for Prometheus");
113+
response = web::ng::Response{std::move(maybeResponse).value(), request};
114+
// notify the coroutine group that the foreign task is done
115+
onTaskComplete();
116+
},
117+
/* isWhiteListed= */ true,
118+
rpc::WorkQueue::Priority::High
99119
);
100-
ASSERT(maybeResponse.has_value(), "Got unexpected request for Prometheus");
101-
return web::ng::Response{std::move(maybeResponse).value(), request};
120+
121+
if (!postSuccessful) {
122+
return web::ng::Response{
123+
boost::beast::http::status::too_many_requests, rpc::makeError(rpc::RippledError::rpcTOO_BUSY), request
124+
};
125+
}
126+
127+
// Put the coroutine to sleep until the foreign task is done
128+
coroutineGroup.asyncWait(yield);
129+
ASSERT(response.has_value(), "Woke up coroutine without setting response");
130+
131+
return std::move(response).value();
102132
}
103133

104134
web::ng::Response

src/app/WebHandlers.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "data/LedgerCacheInterface.hpp"
2323
#include "rpc/Errors.hpp"
24+
#include "rpc/WorkQueue.hpp"
2425
#include "util/log/Logger.hpp"
2526
#include "web/AdminVerificationStrategy.hpp"
2627
#include "web/SubscriptionContextInterface.hpp"
@@ -119,28 +120,31 @@ class DisconnectHook {
119120
*/
120121
class MetricsHandler {
121122
std::shared_ptr<web::AdminVerificationStrategy> adminVerifier_;
123+
std::reference_wrapper<rpc::WorkQueue> workQueue_;
122124

123125
public:
124126
/**
125127
* @brief Construct a new MetricsHandler object
126128
*
127129
* @param adminVerifier The AdminVerificationStrategy to use for verifying the connection for admin access.
130+
* @param workQueue The WorkQueue to use for handling the request.
128131
*/
129-
MetricsHandler(std::shared_ptr<web::AdminVerificationStrategy> adminVerifier);
132+
MetricsHandler(std::shared_ptr<web::AdminVerificationStrategy> adminVerifier, rpc::WorkQueue& workQueue);
130133

131134
/**
132135
* @brief The call of the function object.
133136
*
134137
* @param request The request to handle.
135138
* @param connectionMetadata The connection metadata.
139+
* @param yield The yield context.
136140
* @return The response to the request.
137141
*/
138142
web::ng::Response
139143
operator()(
140144
web::ng::Request const& request,
141145
web::ng::ConnectionMetadata& connectionMetadata,
142146
web::SubscriptionContextPtr,
143-
boost::asio::yield_context
147+
boost::asio::yield_context yield
144148
);
145149
};
146150

tests/unit/app/WebHandlersTests.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "app/WebHandlers.hpp"
2121
#include "rpc/Errors.hpp"
22+
#include "rpc/WorkQueue.hpp"
2223
#include "util/AsioContextTestFixture.hpp"
2324
#include "util/MockLedgerCache.hpp"
2425
#include "util/MockPrometheus.hpp"
@@ -122,7 +123,9 @@ struct MetricsHandlerTests : util::prometheus::WithPrometheus, SyncAsioContextTe
122123
std::make_shared<testing::StrictMock<AdminVerificationStrategyMock>>()
123124
};
124125

125-
MetricsHandler metricsHandler{adminVerifier};
126+
rpc::WorkQueue workQueue{1};
127+
128+
MetricsHandler metricsHandler{adminVerifier, workQueue};
126129
web::ng::Request request{http::request<http::string_body>{http::verb::get, "/metrics", 11}};
127130
};
128131

0 commit comments

Comments
 (0)