From 63cafab56c437eb5e5f7a1274c256bf143cb33e0 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Mon, 2 Feb 2026 17:57:57 +0300 Subject: [PATCH 1/5] api: Coroutinize view_build_statuses handler Further patching will be nicer if this handler is a coroutine Signed-off-by: Pavel Emelyanov --- api/storage_service.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/api/storage_service.cc b/api/storage_service.cc index e50b27e90b..0440120232 100644 --- a/api/storage_service.cc +++ b/api/storage_service.cc @@ -527,13 +527,12 @@ void unset_sstables_loader(http_context& ctx, routes& r) { } void set_view_builder(http_context& ctx, routes& r, sharded& vb, sharded& g) { - ss::view_build_statuses.set(r, [&ctx, &vb, &g] (std::unique_ptr req) { + ss::view_build_statuses.set(r, [&ctx, &vb, &g] (std::unique_ptr req) -> future { auto keyspace = validate_keyspace(ctx, req); auto view = req->get_path_param("view"); - return vb.local().view_build_statuses(std::move(keyspace), std::move(view), g.local()).then([] (std::unordered_map status) { - std::vector res; - return make_ready_future(map_to_key_value(std::move(status), res)); - }); + auto status = co_await vb.local().view_build_statuses(std::move(keyspace), std::move(view), g.local()); + std::vector res; + co_return json::json_return_type(map_to_key_value(std::move(status), res)); }); cf::get_built_indexes.set(r, [&vb](std::unique_ptr req) -> future { From a4bd9037b323fefc0c93edd7730fb98696f1e91c Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Mon, 2 Feb 2026 17:44:48 +0300 Subject: [PATCH 2/5] api: Add map_to_json() helper The get_token_endpoint handler converts iterator of std::map into generated maplist_mapper type. Next patch will do the same for more handlers, so it's good to have a helper converter for it. As a nice side effect, it's possible to avoid multiline lambda argument to stream_range_as_array(). Signed-off-by: Pavel Emelyanov --- api/storage_service.cc | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/api/storage_service.cc b/api/storage_service.cc index 0440120232..8140218540 100644 --- a/api/storage_service.cc +++ b/api/storage_service.cc @@ -570,6 +570,16 @@ static future describe_ring_as_json_for_table(const shar co_return json::json_return_type(stream_range_as_array(co_await ss.local().describe_ring_for_table(keyspace, table), token_range_endpoints_to_json)); } +namespace { +template +storage_service_json::mapper map_to_json(const std::pair& i) { + storage_service_json::mapper val; + val.key = fmt::to_string(i.first); + val.value = fmt::to_string(i.second); + return val; +} +} + static future rest_get_token_endpoint(http_context& ctx, sharded& ss, std::unique_ptr req) { @@ -587,12 +597,7 @@ rest_get_token_endpoint(http_context& ctx, sharded& ss throw bad_param_exception("Either provide both keyspace and table (for tablet table) or neither (for vnodes)"); } - co_return json::json_return_type(stream_range_as_array(token_endpoints, [](const auto& i) { - storage_service_json::mapper val; - val.key = fmt::to_string(i.first); - val.value = fmt::to_string(i.second); - return val; - })); + co_return json::json_return_type(stream_range_as_array(token_endpoints, &map_to_json)); } static From 73512a59ff0dc4a08d92fa127b5f4da3400b2310 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Mon, 2 Feb 2026 17:47:32 +0300 Subject: [PATCH 3/5] api: Streamify few more storage_service/ handlers Like get_token_endpoint one streams the map that it got from storage service, the get_ownership and get_effective_ownership can do the same. Signed-off-by: Pavel Emelyanov --- api/storage_service.cc | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/api/storage_service.cc b/api/storage_service.cc index 8140218540..8934bad71d 100644 --- a/api/storage_service.cc +++ b/api/storage_service.cc @@ -1312,10 +1312,7 @@ rest_get_ownership(http_context& ctx, sharded& ss, std throw httpd::bad_param_exception("storage_service/ownership cannot be used when a keyspace uses tablets"); } - return ss.local().get_ownership().then([] (auto&& ownership) { - std::vector res; - return make_ready_future(map_to_key_value(ownership, res)); - }); + co_return json::json_return_type(stream_range_as_array(co_await ss.local().get_ownership(), &map_to_json)); } static @@ -1332,10 +1329,7 @@ rest_get_effective_ownership(http_context& ctx, sharded res; - return make_ready_future(map_to_key_value(ownership, res)); - }); + co_return json::json_return_type(stream_range_as_array(co_await ss.local().effective_ownership(keyspace_name, table_name), &map_to_json)); } static From dcbb5cb45bbb51f50a752043de8d1d3fbc0ae9b0 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Mon, 2 Feb 2026 17:58:25 +0300 Subject: [PATCH 4/5] api: Streamify view_build_statuses handler Similarly to previous patch, the handler can stream the map of build statuses. Unlike previous patch, it doesn't need to fmt::format() key and value, as these are strings already. It could be a map_to_json partial specialization, but there's so far only one caller, so probably not worth it yet. Signed-off-by: Pavel Emelyanov --- api/storage_service.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/api/storage_service.cc b/api/storage_service.cc index 8934bad71d..8947a3f965 100644 --- a/api/storage_service.cc +++ b/api/storage_service.cc @@ -530,9 +530,12 @@ void set_view_builder(http_context& ctx, routes& r, sharded req) -> future { auto keyspace = validate_keyspace(ctx, req); auto view = req->get_path_param("view"); - auto status = co_await vb.local().view_build_statuses(std::move(keyspace), std::move(view), g.local()); - std::vector res; - co_return json::json_return_type(map_to_key_value(std::move(status), res)); + co_return json::json_return_type(stream_range_as_array(co_await vb.local().view_build_statuses(std::move(keyspace), std::move(view), g.local()), [] (const auto& i) { + storage_service_json::mapper res; + res.key = i.first; + res.value = i.second; + return res; + })); }); cf::get_built_indexes.set(r, [&vb](std::unique_ptr req) -> future { From 44715a2d4583f85cea486bb707132bb984cd395b Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Mon, 2 Feb 2026 17:58:43 +0300 Subject: [PATCH 5/5] api: Remove map_to_key_value() helpers All the callers had already been patched to stream their results directly as json. Signed-off-by: Pavel Emelyanov --- api/api.hh | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/api/api.hh b/api/api.hh index 4a911ae3d7..7607ec4dc0 100644 --- a/api/api.hh +++ b/api/api.hh @@ -23,31 +23,6 @@ namespace api { -template -std::vector map_to_key_value(const std::map& map) { - std::vector res; - res.reserve(map.size()); - - for (const auto& [key, value] : map) { - res.push_back(T()); - res.back().key = key; - res.back().value = value; - } - return res; -} - -template -std::vector& map_to_key_value(const MAP& map, std::vector& res) { - res.reserve(res.size() + std::size(map)); - - for (const auto& [key, value] : map) { - T val; - val.key = fmt::to_string(key); - val.value = fmt::to_string(value); - res.push_back(val); - } - return res; -} template T map_sum(T&& dest, const S& src) { for (const auto& i : src) {