77#include " kv_cache_manager/common/request_context.h"
88#include " kv_cache_manager/config/instance_group.h"
99#include " kv_cache_manager/config/instance_info.h"
10+ #include " kv_cache_manager/config/leader_elector.h"
1011#include " kv_cache_manager/config/registry_manager.h"
1112#include " kv_cache_manager/event/optimizer_stream/subscription_event_sink.h"
1213
1314namespace kv_cache_manager {
1415
1516OptimizerEventServiceGRpc::OptimizerEventServiceGRpc (std::shared_ptr<SubscriptionEventSink> sink,
16- std::shared_ptr<RegistryManager> registry_manager)
17- : sink_(std::move(sink)), registry_manager_(std::move(registry_manager)) {}
17+ std::shared_ptr<RegistryManager> registry_manager,
18+ std::shared_ptr<LeaderElector> leader_elector)
19+ : sink_(std::move(sink))
20+ , registry_manager_(std::move(registry_manager))
21+ , leader_elector_(std::move(leader_elector)) {
22+ DisableSubscriptions ();
23+ }
24+
25+ void OptimizerEventServiceGRpc::EnableSubscriptions () {
26+ if (sink_) {
27+ sink_->EnableSubscriptions ();
28+ }
29+ }
30+
31+ void OptimizerEventServiceGRpc::DisableSubscriptions () {
32+ if (sink_) {
33+ sink_->DisableSubscriptions ();
34+ }
35+ }
36+
37+ bool OptimizerEventServiceGRpc::IsAvailable () const {
38+ return leader_elector_ && leader_elector_->GetRoleState () == RoleState::LEADER &&
39+ leader_elector_->IsStableState () && registry_manager_ && registry_manager_->IsRecoverComplete () && sink_ &&
40+ sink_->accepting_subscriptions () && !sink_->stopped ();
41+ }
1842
1943grpc::Status OptimizerEventServiceGRpc::GetConfiguration (grpc::ServerContext *,
2044 const proto::optimizer::KvcmConfigurationRequest *request,
2145 proto::optimizer::KvcmConfigurationResponse *response) {
2246 auto *status = response->mutable_header ()->mutable_status ();
23- if (!registry_manager_ ) {
47+ if (!IsAvailable () ) {
2448 status->set_code (proto::optimizer::SERVICE_NOT_READY );
25- status->set_message (" KVCM registry manager is unavailable" );
49+ status->set_message (" KVCM is unavailable" );
2650 return grpc::Status::OK ;
2751 }
2852
@@ -76,24 +100,26 @@ grpc::Status
76100OptimizerEventServiceGRpc::SubscribeEvents (grpc::ServerContext *context,
77101 const proto::optimizer::OptimizerEventSubscriptionRequest *request,
78102 grpc::ServerWriter<proto::optimizer::TraceQueryRequest> *writer) {
79- if (!sink_ || sink_-> stopped ()) {
80- return grpc::Status (grpc::StatusCode::UNAVAILABLE , " optimizer event publisher is unavailable" );
103+ if (!IsAvailable ()) {
104+ return grpc::Status (grpc::StatusCode::UNAVAILABLE , " KVCM is unavailable" );
81105 }
82106 auto subscription = sink_->Subscribe (request->consumer_id ());
83107 if (!subscription) {
84- return grpc::Status (grpc::StatusCode::RESOURCE_EXHAUSTED , " optimizer subscriber limit reached " );
108+ return grpc::Status (grpc::StatusCode::UNAVAILABLE , " KVCM is unavailable " );
85109 }
86110
87111 KVCM_LOG_INFO (" OptimizerEventServiceGRpc: stream opened, consumer_id=%s, peer=%s" ,
88112 subscription->consumer_id ().c_str (),
89113 context->peer ().c_str ());
114+ bool subscription_closed = false ;
90115 while (!context->IsCancelled ()) {
91116 proto::optimizer::TraceQueryRequest event;
92117 const auto result = subscription->WaitNext (&event, std::chrono::milliseconds (100 ));
93118 if (result == SubscriptionEventSink::Subscription::WaitResult::kTimeout ) {
94119 continue ;
95120 }
96121 if (result == SubscriptionEventSink::Subscription::WaitResult::kClosed ) {
122+ subscription_closed = true ;
97123 break ;
98124 }
99125 if (!writer->Write (event)) {
@@ -102,6 +128,9 @@ OptimizerEventServiceGRpc::SubscribeEvents(grpc::ServerContext *context,
102128 }
103129 sink_->Unsubscribe (subscription);
104130 KVCM_LOG_INFO (" OptimizerEventServiceGRpc: stream closed, consumer_id=%s" , subscription->consumer_id ().c_str ());
131+ if (subscription_closed) {
132+ return grpc::Status (grpc::StatusCode::UNAVAILABLE , " KVCM is unavailable" );
133+ }
105134 return grpc::Status::OK ;
106135}
107136
0 commit comments