Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
service_registry.cpp
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2024, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
15
16#include <algorithm>
17#include <mutex>
18#include <shared_mutex>
19
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>
24#endif
25
27{
28
29// ============================================================================
30// Utility Functions Implementation
31// ============================================================================
32
33auto parse_method_path(std::string_view full_path)
34 -> std::optional<std::pair<std::string, std::string>>
35{
36 // Expected format: "/package.Service/Method"
37 if (full_path.empty() || full_path[0] != '/')
38 {
39 return std::nullopt;
40 }
41
42 // Remove leading slash
43 auto path = full_path.substr(1);
44
45 // Find the separator between service and method
46 auto pos = path.rfind('/');
47 if (pos == std::string_view::npos || pos == 0 || pos == path.size() - 1)
48 {
49 return std::nullopt;
50 }
51
52 std::string service_name(path.substr(0, pos));
53 std::string method_name(path.substr(pos + 1));
54
55 return std::make_pair(std::move(service_name), std::move(method_name));
56}
57
58auto build_method_path(std::string_view service_name,
59 std::string_view method_name) -> std::string
60{
61 std::string result;
62 result.reserve(1 + service_name.size() + 1 + method_name.size());
63 result += '/';
64 result += service_name;
65 result += '/';
66 result += method_name;
67 return result;
68}
69
70// ============================================================================
71// generic_service Implementation
72// ============================================================================
73
75{
76public:
77 explicit impl(std::string service_name)
78 {
79 // Parse package and service name
80 auto dot_pos = service_name.rfind('.');
81 if (dot_pos != std::string::npos)
82 {
83 descriptor_.package = service_name.substr(0, dot_pos);
84 descriptor_.name = service_name.substr(dot_pos + 1);
85 }
86 else
87 {
88 descriptor_.name = std::move(service_name);
89 }
90 }
91
92 auto descriptor() const -> const service_descriptor&
93 {
94 return descriptor_;
95 }
96
98 const std::string& method_name,
99 unary_handler handler,
100 const std::string& input_type,
101 const std::string& output_type) -> VoidResult
102 {
103 std::lock_guard<std::mutex> lock(mutex_);
104
105 if (unary_handlers_.find(method_name) != unary_handlers_.end())
106 {
107 return error_void(
109 "Method already registered: " + method_name,
110 "generic_service");
111 }
112
113 // Create method descriptor
114 method_descriptor method;
115 method.name = method_name;
116 method.full_name = build_method_path(descriptor_.full_name(), method_name);
117 method.type = method_type::unary;
118 method.input_type = input_type;
119 method.output_type = output_type;
120
121 descriptor_.methods.push_back(std::move(method));
122 unary_handlers_[method_name] = std::move(handler);
123
124 return ok();
125 }
126
128 const std::string& method_name,
130 const std::string& input_type,
131 const std::string& output_type) -> VoidResult
132 {
133 std::lock_guard<std::mutex> lock(mutex_);
134
135 if (server_streaming_handlers_.find(method_name) != server_streaming_handlers_.end())
136 {
137 return error_void(
139 "Method already registered: " + method_name,
140 "generic_service");
141 }
142
143 method_descriptor method;
144 method.name = method_name;
145 method.full_name = build_method_path(descriptor_.full_name(), method_name);
147 method.input_type = input_type;
148 method.output_type = output_type;
149
150 descriptor_.methods.push_back(std::move(method));
151 server_streaming_handlers_[method_name] = std::move(handler);
152
153 return ok();
154 }
155
157 const std::string& method_name,
159 const std::string& input_type,
160 const std::string& output_type) -> VoidResult
161 {
162 std::lock_guard<std::mutex> lock(mutex_);
163
164 if (client_streaming_handlers_.find(method_name) != client_streaming_handlers_.end())
165 {
166 return error_void(
168 "Method already registered: " + method_name,
169 "generic_service");
170 }
171
172 method_descriptor method;
173 method.name = method_name;
174 method.full_name = build_method_path(descriptor_.full_name(), method_name);
176 method.input_type = input_type;
177 method.output_type = output_type;
178
179 descriptor_.methods.push_back(std::move(method));
180 client_streaming_handlers_[method_name] = std::move(handler);
181
182 return ok();
183 }
184
186 const std::string& method_name,
188 const std::string& input_type,
189 const std::string& output_type) -> VoidResult
190 {
191 std::lock_guard<std::mutex> lock(mutex_);
192
193 if (bidi_streaming_handlers_.find(method_name) != bidi_streaming_handlers_.end())
194 {
195 return error_void(
197 "Method already registered: " + method_name,
198 "generic_service");
199 }
200
201 method_descriptor method;
202 method.name = method_name;
203 method.full_name = build_method_path(descriptor_.full_name(), method_name);
205 method.input_type = input_type;
206 method.output_type = output_type;
207
208 descriptor_.methods.push_back(std::move(method));
209 bidi_streaming_handlers_[method_name] = std::move(handler);
210
211 return ok();
212 }
213
214 auto get_unary_handler(const std::string& method_name) const
215 -> const unary_handler*
216 {
217 std::lock_guard<std::mutex> lock(mutex_);
218 auto it = unary_handlers_.find(method_name);
219 return it != unary_handlers_.end() ? &it->second : nullptr;
220 }
221
222 auto get_server_streaming_handler(const std::string& method_name) const
224 {
225 std::lock_guard<std::mutex> lock(mutex_);
226 auto it = server_streaming_handlers_.find(method_name);
227 return it != server_streaming_handlers_.end() ? &it->second : nullptr;
228 }
229
230 auto get_client_streaming_handler(const std::string& method_name) const
232 {
233 std::lock_guard<std::mutex> lock(mutex_);
234 auto it = client_streaming_handlers_.find(method_name);
235 return it != client_streaming_handlers_.end() ? &it->second : nullptr;
236 }
237
238 auto get_bidi_streaming_handler(const std::string& method_name) const
239 -> const bidi_streaming_handler*
240 {
241 std::lock_guard<std::mutex> lock(mutex_);
242 auto it = bidi_streaming_handlers_.find(method_name);
243 return it != bidi_streaming_handlers_.end() ? &it->second : nullptr;
244 }
245
246private:
248 mutable std::mutex mutex_;
249
250 std::unordered_map<std::string, unary_handler> unary_handlers_;
251 std::unordered_map<std::string, server_streaming_handler> server_streaming_handlers_;
252 std::unordered_map<std::string, client_streaming_handler> client_streaming_handlers_;
253 std::unordered_map<std::string, bidi_streaming_handler> bidi_streaming_handlers_;
254};
255
256generic_service::generic_service(std::string service_name)
257 : impl_(std::make_unique<impl>(std::move(service_name)))
258{
259}
260
262
264generic_service& generic_service::operator=(generic_service&&) noexcept = default;
265
266auto generic_service::descriptor() const -> const service_descriptor&
267{
268 return impl_->descriptor();
269}
270
272 const std::string& method_name,
273 unary_handler handler,
274 const std::string& input_type,
275 const std::string& output_type) -> VoidResult
276{
277 return impl_->register_unary_method(method_name, std::move(handler),
278 input_type, output_type);
279}
280
282 const std::string& method_name,
284 const std::string& input_type,
285 const std::string& output_type) -> VoidResult
286{
287 return impl_->register_server_streaming_method(method_name, std::move(handler),
288 input_type, output_type);
289}
290
292 const std::string& method_name,
294 const std::string& input_type,
295 const std::string& output_type) -> VoidResult
296{
297 return impl_->register_client_streaming_method(method_name, std::move(handler),
298 input_type, output_type);
299}
300
302 const std::string& method_name,
304 const std::string& input_type,
305 const std::string& output_type) -> VoidResult
306{
307 return impl_->register_bidi_streaming_method(method_name, std::move(handler),
308 input_type, output_type);
309}
310
311auto generic_service::get_unary_handler(const std::string& method_name) const
312 -> const unary_handler*
313{
314 return impl_->get_unary_handler(method_name);
315}
316
317auto generic_service::get_server_streaming_handler(const std::string& method_name) const
319{
320 return impl_->get_server_streaming_handler(method_name);
321}
322
323auto generic_service::get_client_streaming_handler(const std::string& method_name) const
325{
326 return impl_->get_client_streaming_handler(method_name);
327}
328
329auto generic_service::get_bidi_streaming_handler(const std::string& method_name) const
330 -> const bidi_streaming_handler*
331{
332 return impl_->get_bidi_streaming_handler(method_name);
333}
334
335#if NETWORK_GRPC_OFFICIAL
336auto generic_service::grpc_service() -> ::grpc::Service*
337{
338 // Generic service doesn't have a native gRPC service
339 // It uses the async generic service API
340 return nullptr;
341}
342#endif
343
344// ============================================================================
345// protoc_service_adapter Implementation
346// ============================================================================
347
348#if NETWORK_GRPC_OFFICIAL
349
350class protoc_service_adapter::impl
351{
352public:
353 impl(std::unique_ptr<::grpc::Service> service, std::string service_name)
354 : service_(std::move(service))
355 , owns_service_(true)
356 {
357 init_descriptor(std::move(service_name));
358 }
359
360 impl(::grpc::Service* service, std::string service_name)
361 : service_(std::unique_ptr<::grpc::Service>(service))
362 , owns_service_(true)
363 {
364 init_descriptor(std::move(service_name));
365 }
366
367 ~impl()
368 {
369 if (!owns_service_)
370 {
371 // Release without deleting if we don't own it
372 service_.release();
373 }
374 }
375
376 auto descriptor() const -> const service_descriptor&
377 {
378 return descriptor_;
379 }
380
381 auto grpc_service() -> ::grpc::Service*
382 {
383 return service_.get();
384 }
385
386private:
387 void init_descriptor(std::string service_name)
388 {
389 // Parse package and service name
390 auto dot_pos = service_name.rfind('.');
391 if (dot_pos != std::string::npos)
392 {
393 descriptor_.package = service_name.substr(0, dot_pos);
394 descriptor_.name = service_name.substr(dot_pos + 1);
395 }
396 else
397 {
398 descriptor_.name = std::move(service_name);
399 }
400
401 // Note: Method descriptors would be populated from protobuf reflection
402 // if available. For now, we leave them empty as the protoc-generated
403 // service handles its own method routing.
404 }
405
406 std::unique_ptr<::grpc::Service> service_;
407 bool owns_service_;
408 service_descriptor descriptor_;
409};
410
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)))
415{
416}
417
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)))
422{
423}
424
425protoc_service_adapter::~protoc_service_adapter() = default;
426
427protoc_service_adapter::protoc_service_adapter(protoc_service_adapter&&) noexcept = default;
428protoc_service_adapter& protoc_service_adapter::operator=(protoc_service_adapter&&) noexcept = default;
429
430auto protoc_service_adapter::descriptor() const -> const service_descriptor&
431{
432 return impl_->descriptor();
433}
434
435auto protoc_service_adapter::grpc_service() -> ::grpc::Service*
436{
437 return impl_->grpc_service();
438}
439
440#endif // NETWORK_GRPC_OFFICIAL
441
442// ============================================================================
443// service_registry Implementation
444// ============================================================================
445
447{
448public:
449 explicit impl(const registry_config& config)
450 : config_(config)
451 {
452 }
453
455 {
456 if (service == nullptr)
457 {
458 return error_void(
460 "Service cannot be null",
461 "service_registry");
462 }
463
464 std::lock_guard<std::shared_mutex> lock(mutex_);
465
466 const auto& desc = service->descriptor();
467 auto full_name = desc.full_name();
468
469 if (services_.find(full_name) != services_.end())
470 {
471 return error_void(
473 "Service already registered: " + full_name,
474 "service_registry");
475 }
476
477 services_[full_name] = service;
478
479 // Set initial health status
481 {
482 health_status_[full_name] = true;
483 }
484
485 return ok();
486 }
487
488 auto unregister_service(const std::string& service_name) -> VoidResult
489 {
490 std::lock_guard<std::shared_mutex> lock(mutex_);
491
492 auto it = services_.find(service_name);
493 if (it == services_.end())
494 {
495 return error_void(
497 "Service not found: " + service_name,
498 "service_registry");
499 }
500
501 services_.erase(it);
502 health_status_.erase(service_name);
503
504 return ok();
505 }
506
507 auto find_service(const std::string& service_name) const -> service_base*
508 {
509 std::shared_lock<std::shared_mutex> lock(mutex_);
510
511 auto it = services_.find(service_name);
512 return it != services_.end() ? it->second : nullptr;
513 }
514
515 auto services() const -> std::vector<service_base*>
516 {
517 std::shared_lock<std::shared_mutex> lock(mutex_);
518
519 std::vector<service_base*> result;
520 result.reserve(services_.size());
521 for (const auto& [name, service] : services_)
522 {
523 result.push_back(service);
524 }
525 return result;
526 }
527
528 auto service_names() const -> std::vector<std::string>
529 {
530 std::shared_lock<std::shared_mutex> lock(mutex_);
531
532 std::vector<std::string> result;
533 result.reserve(services_.size());
534 for (const auto& [name, service] : services_)
535 {
536 result.push_back(name);
537 }
538 return result;
539 }
540
541 auto find_method(const std::string& full_method_path) const
542 -> std::optional<std::pair<service_base*, const method_descriptor*>>
543 {
544 auto parsed = parse_method_path(full_method_path);
545 if (!parsed)
546 {
547 return std::nullopt;
548 }
549
550 const auto& [service_name, method_name] = *parsed;
551
552 std::shared_lock<std::shared_mutex> lock(mutex_);
553
554 auto it = services_.find(service_name);
555 if (it == services_.end())
556 {
557 return std::nullopt;
558 }
559
560 auto* service = it->second;
561 const auto* method = service->descriptor().find_method(method_name);
562 if (method == nullptr)
563 {
564 return std::nullopt;
565 }
566
567 return std::make_pair(service, method);
568 }
569
570 auto is_reflection_enabled() const -> bool
571 {
573 }
574
576 {
577 std::shared_lock<std::shared_mutex> lock(mutex_);
578
579 for (const auto& [name, service] : services_)
580 {
581 // Check if service is a generic_service with handlers
582 auto* generic = dynamic_cast<generic_service*>(service);
583 if (generic != nullptr)
584 {
585 const auto& desc = generic->descriptor();
586 for (const auto& method : desc.methods)
587 {
588 VoidResult result = ok();
589 switch (method.type)
590 {
592 {
593 auto* handler = generic->get_unary_handler(method.name);
594 if (handler != nullptr)
595 {
596 result = server.register_unary_method(
597 method.full_name, *handler);
598 }
599 break;
600 }
602 {
603 auto* handler = generic->get_server_streaming_handler(method.name);
604 if (handler != nullptr)
605 {
606 result = server.register_server_streaming_method(
607 method.full_name, *handler);
608 }
609 break;
610 }
612 {
613 auto* handler = generic->get_client_streaming_handler(method.name);
614 if (handler != nullptr)
615 {
616 result = server.register_client_streaming_method(
617 method.full_name, *handler);
618 }
619 break;
620 }
622 {
623 auto* handler = generic->get_bidi_streaming_handler(method.name);
624 if (handler != nullptr)
625 {
626 result = server.register_bidi_streaming_method(
627 method.full_name, *handler);
628 }
629 break;
630 }
631 }
632
633 if (result.is_err())
634 {
635 return result;
636 }
637 }
638 }
639 else
640 {
641 // For non-generic services, use register_service
642 auto result = server.register_service(
643 dynamic_cast<grpc_service*>(service));
644 if (result.is_err())
645 {
646 return result;
647 }
648 }
649 }
650
651 return ok();
652 }
653
654#if NETWORK_GRPC_OFFICIAL
655 auto configure_server_builder(::grpc::ServerBuilder& builder) -> VoidResult
656 {
657 std::shared_lock<std::shared_mutex> lock(mutex_);
658
659 for (const auto& [name, service] : services_)
660 {
661 auto* grpc_svc = service->grpc_service();
662 if (grpc_svc != nullptr)
663 {
664 builder.RegisterService(grpc_svc);
665 }
666 }
667
669 {
670 enable_reflection(builder);
671 }
672
673 return ok();
674 }
675
676 auto enable_reflection(::grpc::ServerBuilder& builder) -> VoidResult
677 {
678 ::grpc::reflection::InitProtoReflectionServerBuilderPlugin();
679 return ok();
680 }
681#endif
682
683 auto set_service_health(const std::string& service_name, bool serving)
684 -> VoidResult
685 {
686 std::lock_guard<std::shared_mutex> lock(mutex_);
687
688 if (!service_name.empty() &&
689 services_.find(service_name) == services_.end())
690 {
691 return error_void(
693 "Service not found: " + service_name,
694 "service_registry");
695 }
696
697 health_status_[service_name] = serving;
698 return ok();
699 }
700
701 auto get_service_health(const std::string& service_name) const -> bool
702 {
703 std::shared_lock<std::shared_mutex> lock(mutex_);
704
705 auto it = health_status_.find(service_name);
706 return it != health_status_.end() ? it->second : false;
707 }
708
709private:
711 mutable std::shared_mutex mutex_;
712 std::unordered_map<std::string, service_base*> services_;
713 std::unordered_map<std::string, bool> health_status_;
714};
715
717 : impl_(std::make_unique<impl>(config))
718{
719}
720
722
724service_registry& service_registry::operator=(service_registry&&) noexcept = default;
725
726auto service_registry::register_service(service_base* service) -> VoidResult
727{
728 return impl_->register_service(service);
729}
730
731auto service_registry::unregister_service(const std::string& service_name) -> VoidResult
732{
733 return impl_->unregister_service(service_name);
734}
735
736auto service_registry::find_service(const std::string& service_name) const
737 -> service_base*
738{
739 return impl_->find_service(service_name);
740}
741
742auto service_registry::services() const -> std::vector<service_base*>
743{
744 return impl_->services();
745}
746
747auto service_registry::service_names() const -> std::vector<std::string>
748{
749 return impl_->service_names();
750}
751
752auto service_registry::find_method(const std::string& full_method_path) const
753 -> std::optional<std::pair<service_base*, const method_descriptor*>>
754{
755 return impl_->find_method(full_method_path);
756}
757
759{
761}
762
764{
765 return impl_->configure_server(server);
766}
767
768#if NETWORK_GRPC_OFFICIAL
769auto service_registry::configure_server_builder(::grpc::ServerBuilder& builder)
770 -> VoidResult
771{
772 return impl_->configure_server_builder(builder);
773}
774
775auto service_registry::enable_reflection(::grpc::ServerBuilder& builder)
776 -> VoidResult
777{
778 return impl_->enable_reflection(builder);
779}
780#endif
781
782auto service_registry::set_service_health(const std::string& service_name,
783 bool serving) -> VoidResult
784{
785 return impl_->set_service_health(service_name, serving);
786}
787
788auto service_registry::get_service_health(const std::string& service_name) const
789 -> bool
790{
791 return impl_->get_service_health(service_name);
792}
793
794// ============================================================================
795// health_service Implementation
796// ============================================================================
797
799{
800public:
802 {
803 descriptor_.name = "Health";
804 descriptor_.package = "grpc.health.v1";
805
806 method_descriptor check_method;
807 check_method.name = "Check";
808 check_method.full_name = "/grpc.health.v1.Health/Check";
809 check_method.type = method_type::unary;
810 check_method.input_type = "grpc.health.v1.HealthCheckRequest";
811 check_method.output_type = "grpc.health.v1.HealthCheckResponse";
812 descriptor_.methods.push_back(std::move(check_method));
813
814 method_descriptor watch_method;
815 watch_method.name = "Watch";
816 watch_method.full_name = "/grpc.health.v1.Health/Watch";
817 watch_method.type = method_type::server_streaming;
818 watch_method.input_type = "grpc.health.v1.HealthCheckRequest";
819 watch_method.output_type = "grpc.health.v1.HealthCheckResponse";
820 descriptor_.methods.push_back(std::move(watch_method));
821 }
822
823 auto descriptor() const -> const service_descriptor&
824 {
825 return descriptor_;
826 }
827
828 auto set_status(const std::string& service_name, health_status status) -> void
829 {
830 std::lock_guard<std::mutex> lock(mutex_);
831 status_map_[service_name] = status;
832 }
833
834 auto get_status(const std::string& service_name) const -> health_status
835 {
836 std::lock_guard<std::mutex> lock(mutex_);
837 auto it = status_map_.find(service_name);
838 if (it == status_map_.end())
839 {
841 }
842 return it->second;
843 }
844
845 auto clear() -> void
846 {
847 std::lock_guard<std::mutex> lock(mutex_);
848 status_map_.clear();
849 }
850
851private:
853 mutable std::mutex mutex_;
854 std::unordered_map<std::string, health_status> status_map_;
855};
856
858 : impl_(std::make_unique<impl>())
859{
860}
861
863
865health_service& health_service::operator=(health_service&&) noexcept = default;
866
867auto health_service::descriptor() const -> const service_descriptor&
868{
869 return impl_->descriptor();
870}
871
872auto health_service::set_status(const std::string& service_name,
873 health_status status) -> void
874{
875 impl_->set_status(service_name, status);
876}
877
878auto health_service::get_status(const std::string& service_name) const
880{
881 return impl_->get_status(service_name);
882}
883
885{
886 impl_->clear();
887}
888
889#if NETWORK_GRPC_OFFICIAL
890auto health_service::grpc_service() -> ::grpc::Service*
891{
892 // Health service uses the standard gRPC health check implementation
893 // when available. For now, return nullptr as we handle it via generic.
894 return nullptr;
895}
896#endif
897
898} // namespace kcenon::network::protocols::grpc
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
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 *
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.
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
Definition server.h:273
Base class for gRPC service implementations.
Definition server.h:236
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
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.
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
std::unordered_map< std::string, bool > health_status_
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.
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.
tracing_config config
Definition exporters.cpp:29
gRPC protocol implementation
Definition client.h:34
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.
@ 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.
Definition server.h:134
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.
Definition server.h:163
@ 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.
Definition server.h:222
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.
Definition server.h:197
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")
std::string name
Method name (without service prefix)
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")