18#include <shared_mutex>
20#if NETWORK_GRPC_OFFICIAL
21#include <grpcpp/grpcpp.h>
22#include <grpcpp/ext/proto_server_reflection_plugin.h>
23#include <grpcpp/health_check_service_interface.h>
34 -> std::optional<std::pair<std::string, std::string>>
37 if (full_path.empty() || full_path[0] !=
'/')
43 auto path = full_path.substr(1);
46 auto pos = path.rfind(
'/');
47 if (pos == std::string_view::npos || pos == 0 || pos == path.size() - 1)
52 std::string service_name(path.substr(0, pos));
53 std::string method_name(path.substr(pos + 1));
55 return std::make_pair(std::move(service_name), std::move(method_name));
59 std::string_view method_name) -> std::string
62 result.reserve(1 + service_name.size() + 1 + method_name.size());
64 result += service_name;
66 result += method_name;
77 explicit impl(std::string service_name)
80 auto dot_pos = service_name.rfind(
'.');
81 if (dot_pos != std::string::npos)
98 const std::string& method_name,
100 const std::string& input_type,
103 std::lock_guard<std::mutex> lock(
mutex_);
109 "Method already registered: " + method_name,
115 method.
name = method_name;
128 const std::string& method_name,
130 const std::string& input_type,
133 std::lock_guard<std::mutex> lock(
mutex_);
139 "Method already registered: " + method_name,
144 method.
name = method_name;
157 const std::string& method_name,
159 const std::string& input_type,
162 std::lock_guard<std::mutex> lock(
mutex_);
168 "Method already registered: " + method_name,
173 method.
name = method_name;
186 const std::string& method_name,
188 const std::string& input_type,
191 std::lock_guard<std::mutex> lock(
mutex_);
197 "Method already registered: " + method_name,
202 method.
name = method_name;
217 std::lock_guard<std::mutex> lock(
mutex_);
225 std::lock_guard<std::mutex> lock(
mutex_);
233 std::lock_guard<std::mutex> lock(
mutex_);
241 std::lock_guard<std::mutex> lock(
mutex_);
257 : impl_(std::make_unique<
impl>(std::move(service_name)))
268 return impl_->descriptor();
272 const std::string& method_name,
274 const std::string& input_type,
277 return impl_->register_unary_method(method_name, std::move(handler),
278 input_type, output_type);
282 const std::string& method_name,
284 const std::string& input_type,
287 return impl_->register_server_streaming_method(method_name, std::move(handler),
288 input_type, output_type);
292 const std::string& method_name,
294 const std::string& input_type,
297 return impl_->register_client_streaming_method(method_name, std::move(handler),
298 input_type, output_type);
302 const std::string& method_name,
304 const std::string& input_type,
307 return impl_->register_bidi_streaming_method(method_name, std::move(handler),
308 input_type, output_type);
314 return impl_->get_unary_handler(method_name);
320 return impl_->get_server_streaming_handler(method_name);
326 return impl_->get_client_streaming_handler(method_name);
332 return impl_->get_bidi_streaming_handler(method_name);
335#if NETWORK_GRPC_OFFICIAL
336auto generic_service::grpc_service() -> ::grpc::Service*
348#if NETWORK_GRPC_OFFICIAL
350class protoc_service_adapter::impl
353 impl(std::unique_ptr<::grpc::Service> service, std::string service_name)
354 : service_(std::move(service))
355 , owns_service_(true)
357 init_descriptor(std::move(service_name));
360 impl(::grpc::Service* service, std::string service_name)
361 : service_(std::unique_ptr<::grpc::Service>(service))
362 , owns_service_(true)
364 init_descriptor(std::move(service_name));
376 auto descriptor() const -> const service_descriptor&
381 auto grpc_service() -> ::grpc::Service*
383 return service_.get();
387 void init_descriptor(std::string service_name)
390 auto dot_pos = service_name.rfind(
'.');
391 if (dot_pos != std::string::npos)
393 descriptor_.package = service_name.substr(0, dot_pos);
394 descriptor_.name = service_name.substr(dot_pos + 1);
398 descriptor_.name = std::move(service_name);
406 std::unique_ptr<::grpc::Service> service_;
408 service_descriptor descriptor_;
411protoc_service_adapter::protoc_service_adapter(
412 std::unique_ptr<::grpc::Service> service,
413 std::string service_name)
414 : impl_(std::make_unique<impl>(std::move(service), std::move(service_name)))
418protoc_service_adapter::protoc_service_adapter(
419 ::grpc::Service* service,
420 std::string service_name)
421 : impl_(std::make_unique<impl>(service, std::move(service_name)))
425protoc_service_adapter::~protoc_service_adapter() =
default;
427protoc_service_adapter::protoc_service_adapter(protoc_service_adapter&&) noexcept = default;
428protoc_service_adapter& protoc_service_adapter::operator=(protoc_service_adapter&&) noexcept = default;
430auto protoc_service_adapter::descriptor() const -> const service_descriptor&
432 return impl_->descriptor();
435auto protoc_service_adapter::grpc_service() -> ::grpc::Service*
437 return impl_->grpc_service();
456 if (service ==
nullptr)
460 "Service cannot be null",
464 std::lock_guard<std::shared_mutex> lock(
mutex_);
466 const auto& desc = service->descriptor();
467 auto full_name = desc.full_name();
473 "Service already registered: " + full_name,
490 std::lock_guard<std::shared_mutex> lock(
mutex_);
497 "Service not found: " + service_name,
509 std::shared_lock<std::shared_mutex> lock(
mutex_);
512 return it !=
services_.end() ? it->second :
nullptr;
517 std::shared_lock<std::shared_mutex> lock(
mutex_);
519 std::vector<service_base*> result;
521 for (
const auto& [name, service] :
services_)
523 result.push_back(service);
530 std::shared_lock<std::shared_mutex> lock(
mutex_);
532 std::vector<std::string> result;
534 for (
const auto& [name, service] :
services_)
536 result.push_back(name);
542 -> std::optional<std::pair<service_base*, const method_descriptor*>>
550 const auto& [service_name, method_name] = *parsed;
552 std::shared_lock<std::shared_mutex> lock(
mutex_);
560 auto* service = it->second;
561 const auto* method = service->descriptor().find_method(method_name);
562 if (method ==
nullptr)
567 return std::make_pair(service, method);
577 std::shared_lock<std::shared_mutex> lock(
mutex_);
579 for (
const auto& [name, service] :
services_)
583 if (generic !=
nullptr)
585 const auto& desc =
generic->descriptor();
586 for (
const auto& method : desc.methods)
593 auto* handler =
generic->get_unary_handler(method.name);
594 if (handler !=
nullptr)
596 result = server.register_unary_method(
597 method.full_name, *handler);
603 auto* handler =
generic->get_server_streaming_handler(method.name);
604 if (handler !=
nullptr)
606 result = server.register_server_streaming_method(
607 method.full_name, *handler);
613 auto* handler =
generic->get_client_streaming_handler(method.name);
614 if (handler !=
nullptr)
616 result = server.register_client_streaming_method(
617 method.full_name, *handler);
623 auto* handler =
generic->get_bidi_streaming_handler(method.name);
624 if (handler !=
nullptr)
626 result = server.register_bidi_streaming_method(
627 method.full_name, *handler);
642 auto result = server.register_service(
654#if NETWORK_GRPC_OFFICIAL
655 auto configure_server_builder(::grpc::ServerBuilder& builder) ->
VoidResult
657 std::shared_lock<std::shared_mutex> lock(
mutex_);
659 for (
const auto& [name, service] :
services_)
661 auto* grpc_svc = service->grpc_service();
662 if (grpc_svc !=
nullptr)
664 builder.RegisterService(grpc_svc);
670 enable_reflection(builder);
676 auto enable_reflection(::grpc::ServerBuilder& builder) ->
VoidResult
678 ::grpc::reflection::InitProtoReflectionServerBuilderPlugin();
686 std::lock_guard<std::shared_mutex> lock(
mutex_);
688 if (!service_name.empty() &&
693 "Service not found: " + service_name,
703 std::shared_lock<std::shared_mutex> lock(
mutex_);
712 std::unordered_map<std::string, service_base*>
services_;
728 return impl_->register_service(service);
733 return impl_->unregister_service(service_name);
739 return impl_->find_service(service_name);
753 -> std::optional<std::pair<service_base*, const method_descriptor*>>
755 return impl_->find_method(full_method_path);
765 return impl_->configure_server(server);
768#if NETWORK_GRPC_OFFICIAL
769auto service_registry::configure_server_builder(::grpc::ServerBuilder& builder)
772 return impl_->configure_server_builder(builder);
775auto service_registry::enable_reflection(::grpc::ServerBuilder& builder)
778 return impl_->enable_reflection(builder);
785 return impl_->set_service_health(service_name,
serving);
791 return impl_->get_service_health(service_name);
807 check_method.
name =
"Check";
808 check_method.
full_name =
"/grpc.health.v1.Health/Check";
810 check_method.
input_type =
"grpc.health.v1.HealthCheckRequest";
811 check_method.
output_type =
"grpc.health.v1.HealthCheckResponse";
815 watch_method.
name =
"Watch";
816 watch_method.
full_name =
"/grpc.health.v1.Health/Watch";
818 watch_method.
input_type =
"grpc.health.v1.HealthCheckRequest";
819 watch_method.
output_type =
"grpc.health.v1.HealthCheckResponse";
830 std::lock_guard<std::mutex> lock(
mutex_);
836 std::lock_guard<std::mutex> lock(
mutex_);
847 std::lock_guard<std::mutex> lock(
mutex_);
858 : impl_(std::make_unique<
impl>())
869 return impl_->descriptor();
875 impl_->set_status(service_name, status);
881 return impl_->get_status(service_name);
889#if NETWORK_GRPC_OFFICIAL
890auto health_service::grpc_service() -> ::grpc::Service*
std::unordered_map< std::string, server_streaming_handler > server_streaming_handlers_
std::unordered_map< std::string, client_streaming_handler > client_streaming_handlers_
auto register_bidi_streaming_method(const std::string &method_name, bidi_streaming_handler handler, const std::string &input_type, const std::string &output_type) -> VoidResult
std::unordered_map< std::string, unary_handler > unary_handlers_
std::unordered_map< std::string, bidi_streaming_handler > bidi_streaming_handlers_
auto register_server_streaming_method(const std::string &method_name, server_streaming_handler handler, const std::string &input_type, const std::string &output_type) -> VoidResult
auto get_server_streaming_handler(const std::string &method_name) const -> const server_streaming_handler *
auto register_unary_method(const std::string &method_name, unary_handler handler, const std::string &input_type, const std::string &output_type) -> VoidResult
auto descriptor() const -> const service_descriptor &
auto register_client_streaming_method(const std::string &method_name, client_streaming_handler handler, const std::string &input_type, const std::string &output_type) -> VoidResult
impl(std::string service_name)
auto get_unary_handler(const std::string &method_name) const -> const unary_handler *
auto get_client_streaming_handler(const std::string &method_name) const -> const client_streaming_handler *
auto get_bidi_streaming_handler(const std::string &method_name) const -> const bidi_streaming_handler *
service_descriptor descriptor_
A service that allows dynamic method registration.
auto register_bidi_streaming_method(const std::string &method_name, bidi_streaming_handler handler, const std::string &input_type="", const std::string &output_type="") -> VoidResult
Register a bidirectional streaming method handler.
generic_service(std::string service_name)
Construct a generic service.
auto register_client_streaming_method(const std::string &method_name, client_streaming_handler handler, const std::string &input_type="", const std::string &output_type="") -> VoidResult
Register a client streaming method handler.
auto get_server_streaming_handler(const std::string &method_name) const -> const server_streaming_handler *
Get server streaming handler for a method.
auto get_bidi_streaming_handler(const std::string &method_name) const -> const bidi_streaming_handler *
Get bidirectional streaming handler for a method.
auto register_server_streaming_method(const std::string &method_name, server_streaming_handler handler, const std::string &input_type="", const std::string &output_type="") -> VoidResult
Register a server streaming method handler.
auto get_client_streaming_handler(const std::string &method_name) const -> const client_streaming_handler *
Get client streaming handler for a method.
auto get_unary_handler(const std::string &method_name) const -> const unary_handler *
Get unary handler for a method.
~generic_service() override
auto register_unary_method(const std::string &method_name, unary_handler handler, const std::string &input_type="", const std::string &output_type="") -> VoidResult
Register a unary method handler.
gRPC server for handling RPC requests
Base class for gRPC service implementations.
auto get_status(const std::string &service_name) const -> health_status
std::unordered_map< std::string, health_status > status_map_
auto descriptor() const -> const service_descriptor &
auto set_status(const std::string &service_name, health_status status) -> void
service_descriptor descriptor_
Implementation of gRPC health checking protocol.
auto clear() -> void
Clear all health statuses.
auto get_status(const std::string &service_name) const -> health_status
Get health status for a service.
~health_service() override
auto set_status(const std::string &service_name, health_status status) -> void
Set health status for a service.
Base class for all gRPC service implementations.
auto find_service(const std::string &service_name) const -> service_base *
auto set_service_health(const std::string &service_name, bool serving) -> VoidResult
std::unordered_map< std::string, service_base * > services_
auto services() const -> std::vector< service_base * >
auto find_method(const std::string &full_method_path) const -> std::optional< std::pair< service_base *, const method_descriptor * > >
auto configure_server(grpc_server &server) -> VoidResult
auto get_service_health(const std::string &service_name) const -> bool
auto unregister_service(const std::string &service_name) -> VoidResult
auto register_service(service_base *service) -> VoidResult
impl(const registry_config &config)
std::unordered_map< std::string, bool > health_status_
auto is_reflection_enabled() const -> bool
auto service_names() const -> std::vector< std::string >
Central registry for managing gRPC services.
auto service_names() const -> std::vector< std::string >
Get list of all service names.
auto get_service_health(const std::string &service_name) const -> bool
Get health status for a service.
auto unregister_service(const std::string &service_name) -> VoidResult
Unregister a service.
auto find_service(const std::string &service_name) const -> service_base *
Find a service by name.
std::unique_ptr< impl > impl_
auto set_service_health(const std::string &service_name, bool serving) -> VoidResult
Set health status for a service.
auto services() const -> std::vector< service_base * >
Get all registered services.
service_registry(const registry_config &config={})
Construct service registry.
auto is_reflection_enabled() const -> bool
Check if reflection is enabled.
auto find_method(const std::string &full_method_path) const -> std::optional< std::pair< service_base *, const method_descriptor * > >
Find a method by full path.
auto configure_server(grpc_server &server) -> VoidResult
Configure a gRPC server with registered services.
constexpr int invalid_argument
constexpr int already_exists
gRPC protocol implementation
auto parse_method_path(std::string_view full_path) -> std::optional< std::pair< std::string, std::string > >
Parse full method path into service and method names.
health_status
Health status for a service.
@ service_unknown
Service is not registered.
@ serving
Service is serving.
@ server_streaming
Server streaming (single request, multiple responses)
@ client_streaming
Client streaming (multiple requests, single response)
@ bidi_streaming
Bidirectional streaming (multiple requests and responses)
@ unary
Unary RPC (single request, single response)
std::function< std::pair< grpc_status, std::vector< uint8_t > >( server_context &ctx, const std::vector< uint8_t > &request)> unary_handler
Handler function type for unary RPC.
auto build_method_path(std::string_view service_name, std::string_view method_name) -> std::string
Build full method path from service and method names.
std::function< grpc_status( server_context &ctx, const std::vector< uint8_t > &request, server_writer &writer)> server_streaming_handler
Handler function type for server streaming RPC.
@ ok
Not an error; returned on success.
std::function< grpc_status( server_context &ctx, server_reader_writer &stream)> bidi_streaming_handler
Handler function type for bidirectional streaming RPC.
std::function< std::pair< grpc_status, std::vector< uint8_t > >( server_context &ctx, server_reader &reader)> client_streaming_handler
Handler function type for client streaming RPC.
Result< std::monostate > VoidResult
VoidResult error_void(int code, const std::string &message, const std::string &source="network_system", const std::string &details="")
gRPC server configuration and service hosting.
gRPC service registration mechanism
Describes a single RPC method within a service.
std::string output_type
Output message type name (for reflection)
std::string input_type
Input message type name (for reflection)
std::string full_name
Full method path (e.g., "/package.Service/Method")
method_type type
Type of RPC method.
std::string name
Method name (without service prefix)
Configuration for service registry.
bool enable_health_check
Enable health checking service.
bool enable_reflection
Enable reflection service for debugging.
Describes a gRPC service and its methods.
auto full_name() const -> std::string
Get full service name including package.
std::vector< method_descriptor > methods
List of methods in this service.
std::string name
Service name (e.g., "helloworld.Greeter")
std::string package
Package name (e.g., "helloworld")