| #include "static_state.h" |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "daemon_context.h" |
| #include "state_updater.h" |
| #include "absl/functional/any_invocable.h" |
| #include "absl/functional/bind_front.h" |
| #include "absl/log/log.h" |
| #include "absl/status/status.h" |
| #include "absl/status/statusor.h" |
| #include "absl/time/time.h" |
| |
| namespace safepower_agent { |
| |
| StaticStateLoader::StaticStateLoader( |
| std::string 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) { |
| TryLoadState(); |
| } |
| |
| StaticStateLoader::StaticStateLoader( |
| std::string 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( |
| name, |
| [get_state = std::move(get_state)]( |
| StaticStateLoader::GetStateCallback callback) mutable { |
| callback(get_state()); |
| }, |
| state_updater, config) {} |
| |
| 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::TryLoadState() { |
| get_state_([this](absl::StatusOr<safepower_agent_proto::SystemState> state) { |
| if (!state.ok()) { |
| LOG(ERROR) << name_ << ": Failed to get state: " << state.status(); |
| if (retries_left_ == 0 || |
| DaemonContext::Get().now() + retry_interval_ >= timeout_time_) { |
| LOG(ERROR) << name_ << ": retries exhausted"; |
| return; |
| } |
| if (retries_left_ > 0) { |
| retries_left_--; |
| } |
| absl::Status scheduler_status = |
| DaemonContext::Get().scheduler().DelayCall( |
| absl::bind_front(&StaticStateLoader::TryLoadState, this), |
| retry_interval_, name_); |
| if (!scheduler_status.ok()) { |
| LOG(ERROR) << name_ |
| << " Failed to schedule retry: " << scheduler_status; |
| } |
| return; |
| } |
| LOG(INFO) << name_ << ": Successfully got state: " << *state; |
| state_updater_->UpdateState(*std::move(state)); |
| }); |
| } |
| |
| } // namespace safepower_agent |