3#include <spdlog/spdlog.h>
8 : enable_multithreading_(enable_multithreading),
9 thread_pool_(enable_multithreading ? num_threads : 0) {
11 if (enable_multithreading_) {
13 "Dispatcher initialized with multithreading support using {} threads",
16 spdlog::info(
"Dispatcher initialized without multithreading support");
21 -> std::optional<std::string> {
22 auto request_json = ParseAndValidateJson(request_str);
23 if (!request_json.has_value()) {
27 if (request_json->is_array()) {
28 return DispatchBatchRequest(*request_json);
31 return DispatchSingleRequest(*request_json);
34auto Dispatcher::ParseAndValidateJson(
const std::string &request_str)
35 -> std::optional<nlohmann::json> {
37 return nlohmann::json::parse(request_str);
38 }
catch (
const nlohmann::json::parse_error &) {
39 spdlog::error(
"JSON parsing error: {}", request_str);
44auto Dispatcher::DispatchSingleRequest(
const nlohmann::json &request_json)
45 -> std::optional<std::string> {
46 auto response_json = DispatchSingleRequestInner(request_json);
47 if (response_json.has_value()) {
48 return response_json->dump();
53auto Dispatcher::DispatchSingleRequestInner(
const nlohmann::json &request_json)
54 -> std::optional<nlohmann::json> {
55 auto validation_error = ValidateRequest(request_json);
56 if (validation_error.has_value()) {
57 return validation_error->ToJson();
61 spdlog::info(
"Dispatching request: method={}", request.GetMethod());
63 auto optional_handler = FindHandler(handlers_, request.GetMethod());
64 if (!optional_handler.has_value()) {
65 if (request.GetId().has_value()) {
70 spdlog::warn(
"Method {} not found for notification", request.GetMethod());
74 return HandleRequest(request, optional_handler.value());
77auto Dispatcher::DispatchBatchRequest(
const nlohmann::json &request_json)
78 -> std::optional<std::string> {
79 if (request_json.empty()) {
80 spdlog::warn(
"Empty batch request");
84 auto response_jsons = DispatchBatchRequestInner(request_json);
85 if (response_jsons.empty()) {
89 return nlohmann::json(response_jsons).dump();
92auto Dispatcher::DispatchBatchRequestInner(
const nlohmann::json &request_json)
93 -> std::vector<nlohmann::json> {
94 std::vector<std::future<std::optional<nlohmann::json>>> futures;
96 for (
const auto &element : request_json) {
97 if (enable_multithreading_) {
98 futures.emplace_back(thread_pool_.submit_task(
99 [
this, element]() -> std::optional<nlohmann::json> {
100 return DispatchSingleRequestInner(element);
103 futures.emplace_back(std::async(
104 std::launch::deferred,
105 [
this, element]() -> std::optional<nlohmann::json> {
106 return DispatchSingleRequestInner(element);
111 std::vector<nlohmann::json> responses;
112 for (
auto &future : futures) {
113 std::optional<nlohmann::json> response = future.get();
114 if (response.has_value()) {
115 responses.push_back(response.value());
122auto Dispatcher::ValidateRequest(
const nlohmann::json &request_json)
123 -> std::optional<Response> {
124 if (!request_json.is_object()) {
128 if (!request_json.contains(
"jsonrpc") || request_json[
"jsonrpc"] !=
"2.0") {
132 if (!request_json.contains(
"method")) {
133 if (request_json.contains(
"id")) {
138 spdlog::warn(
"Request missing method field and id");
142 if (!request_json[
"method"].is_string()) {
149auto Dispatcher::FindHandler(
150 const std::unordered_map<std::string, Handler> &handlers,
151 const std::string &method) -> std::optional<Handler> {
152 auto it = handlers.find(method);
153 if (it != handlers.end()) {
159auto Dispatcher::HandleRequest(
const Request &request,
const Handler &handler)
160 -> std::optional<nlohmann::json> {
161 if (request.GetId().has_value()) {
163 if (std::holds_alternative<MethodCallHandler>(handler)) {
164 const auto &method_call_handler = std::get<MethodCallHandler>(handler);
165 Response response = HandleMethodCall(request, method_call_handler);
166 return response.ToJson();
173 if (std::holds_alternative<NotificationHandler>(handler)) {
174 const auto ¬ification_handler = std::get<NotificationHandler>(handler);
175 HandleNotification(request, notification_handler);
182auto Dispatcher::HandleMethodCall(
185 nlohmann::json response_json = handler(request.GetParams());
187 "Method call {} returned: {}", request.GetMethod(),
188 response_json.dump());
191 }
catch (
const std::exception &e) {
192 spdlog::error(
"Exception during method call handling: {}", e.what());
198void Dispatcher::HandleNotification(
201 handler(request.GetParams());
202 spdlog::info(
"Notification {} handled successfully", request.GetMethod());
203 }
catch (
const std::exception &e) {
204 spdlog::error(
"Exception during notification handling: {}", e.what());
210 handlers_[method] = handler;
211 spdlog::info(
"Dispatcher registered method call: {}", method);
216 handlers_[method] = handler;
217 spdlog::info(
"Dispatcher registered notification: {}", method);
Dispatcher(bool enable_multithreading=true, size_t num_threads=std::thread::hardware_concurrency())
Constructs a Dispatcher.
void RegisterMethodCall(const std::string &method, const MethodCallHandler &handler)
Registers a method call handler.
auto DispatchRequest(const std::string &request) -> std::optional< std::string >
Processes a JSON-RPC request.
void RegisterNotification(const std::string &method, const NotificationHandler &handler)
Registers a notification handler.
static auto FromJson(const nlohmann::json &json_obj) -> Request
Creates a Request object from a JSON object.
static auto CreateLibError(LibErrorKind error_kind, const std::optional< nlohmann::json > &id=std::nullopt) -> Response
Creates a Response object for a library error.
static auto FromUserResponse(const nlohmann::json &response_json, std::optional< nlohmann::json > id) -> Response
Creates a Response object from a JSON object that represents a user response.
std::function< void(const std::optional< nlohmann::json > &)> NotificationHandler
Type alias for notification handler functions.
std::variant< MethodCallHandler, NotificationHandler > Handler
Type alias for a handler which can be either a method call handler or a notification handler.
std::function< nlohmann::json(const std::optional< nlohmann::json > &)> MethodCallHandler
Type alias for method call handler functions.