| #include "static_state.h" |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "daemon_context.h" |
| #include "safepower_agent.pb.h" |
| #include "state_updater.h" |
| #include "absl/functional/any_invocable.h" |
| #include "absl/log/log.h" |
| #include "absl/status/status.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/string_view.h" |
| #include "absl/time/time.h" |
| |
| namespace safepower_agent { |
| |
| std::shared_ptr<StaticStateLoader> StaticStateLoader::Create( |
| absl::string_view name, |
| absl::AnyInvocable<absl::StatusOr<safepower_agent_proto::SystemState>()> |
| get_state, |
| std::shared_ptr<StateUpdater<safepower_agent_proto::SystemState>> |
| state_updater, |
| const StaticStateLoaderConfig& config) { |
| auto loader = std::make_shared<StaticStateLoader>( |
| PrivateToken{}, name, std::move(get_state), state_updater, config); |
| loader->Start(); |
| return loader; |
| } |
| |
| std::shared_ptr<StaticStateLoader> StaticStateLoader::Create( |
| absl::string_view name, |
| absl::AnyInvocable<void(GetStateCallback)> get_state, |
| std::shared_ptr<StateUpdater<safepower_agent_proto::SystemState>> |
| state_updater, |
| const StaticStateLoaderConfig& config) { |
| auto loader = std::make_shared<StaticStateLoader>( |
| PrivateToken{}, name, std::move(get_state), state_updater, config); |
| loader->Start(); |
| return loader; |
| } |
| |
| StaticStateLoader::StaticStateLoader( |
| PrivateToken token, absl::string_view name, |
| absl::AnyInvocable<absl::StatusOr<safepower_agent_proto::SystemState>()> |
| get_state, |
| std::shared_ptr<StateUpdater<safepower_agent_proto::SystemState>> |
| state_updater, |
| const StaticStateLoaderConfig& config) |
| : StaticStateLoader( |
| token, name, |
| [get_state = std::move(get_state)]( |
| StaticStateLoader::GetStateCallback callback) mutable { |
| callback(get_state()); |
| }, |
| state_updater, config) {} |
| |
| StaticStateLoader::StaticStateLoader( |
| PrivateToken /*token*/, absl::string_view name, |
| absl::AnyInvocable<void(GetStateCallback)> get_state, |
| std::shared_ptr<StateUpdater<safepower_agent_proto::SystemState>> |
| state_updater, |
| const StaticStateLoaderConfig& config) |
| : name_(name), |
| get_state_(std::move(get_state)), |
| state_updater_(std::move(state_updater)), |
| retry_interval_(config.retry_interval), |
| timeout_time_(DaemonContext::Get().now() + config.timeout), |
| retries_left_(config.max_retries) {} |
| |
| StaticStateLoader::~StaticStateLoader() { |
| absl::Status status = DaemonContext::Get().scheduler().CancelCall(name_); |
| if (status.ok()) { |
| LOG(WARNING) << "Cancelled pending state load for " << name_; |
| } else if (!absl::IsNotFound(status)) { |
| LOG(ERROR) << name_ << " Failed to cancel call: " << status; |
| } |
| } |
| |
| void StaticStateLoader::Start() { |
| TryLoadState(); |
| } |
| |
| void StaticStateLoader::TryLoadState() { |
| get_state_([weak_this = weak_from_this()]( |
| absl::StatusOr<safepower_agent_proto::SystemState> state) { |
| auto self = weak_this.lock(); |
| if (!self) { |
| return; |
| } |
| if (!state.ok()) { |
| LOG(ERROR) << self->name_ << ": Failed to get state: " << state.status(); |
| if (self->retries_left_ == 0 || |
| DaemonContext::Get().now() + self->retry_interval_ >= |
| self->timeout_time_) { |
| LOG(ERROR) << self->name_ << ": retries exhausted"; |
| return; |
| } |
| if (self->retries_left_ > 0) { |
| self->retries_left_--; |
| } |
| absl::Status scheduler_status = |
| DaemonContext::Get().scheduler().DelayCall( |
| [weak_this]() { |
| if (auto self = weak_this.lock()) { |
| self->TryLoadState(); |
| } |
| }, |
| self->retry_interval_, self->name_); |
| if (!scheduler_status.ok()) { |
| LOG(ERROR) << self->name_ |
| << " Failed to schedule retry: " << scheduler_status; |
| } |
| return; |
| } |
| LOG(INFO) << self->name_ << ": Successfully got state: " << *state; |
| self->state_updater_->UpdateState(*std::move(state)); |
| }); |
| } |
| |
| } // namespace safepower_agent |