blob: 9de83bf486c85fdb56310156f2da00a02f5ca9d8 [file]
#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