blob: 0abeda156168e94e5f5837a5825c63a921ec37f2 [file] [log] [blame]
#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