blob: 3e7125753a7843f4ca034a6943d0b13939ece31d [file] [log] [blame]
#ifndef PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_DISRUPTION_MANAGER_H_
#define PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_DISRUPTION_MANAGER_H_
#include "callback_manager.h"
#include "absl/base/thread_annotations.h"
#include "absl/functional/any_invocable.h"
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
#include "source_location"
namespace safepower_agent {
class DisruptionManager {
public:
using DisruptionCallback = absl::AnyInvocable<void() &&>;
using CallbackHandle = CallbackManager::Handle;
DisruptionManager() = default;
DisruptionManager(const DisruptionManager&) = delete;
DisruptionManager& operator=(const DisruptionManager&) = delete;
DisruptionManager(DisruptionManager&&) = delete;
DisruptionManager& operator=(DisruptionManager&&) = delete;
// Indicates that a disruption is expected to happen in the near future.
// Returns an error if there is already a pending disruption.
absl::Status ExpectDisruptionIn(absl::Duration timeout)
ABSL_LOCKS_EXCLUDED(disruption_mutex_);
// Cancels the pending disruption. Returns an error if there is no pending
// disruption.
absl::Status CancelDisruption() ABSL_LOCKS_EXCLUDED(disruption_mutex_);
// Returns the remaining duration of the pending disruption, or zero if there
// is no pending disruption.
absl::Duration PendingDisruption() const
ABSL_LOCKS_EXCLUDED(disruption_mutex_);
// Runs a callback when a disruption is expected. The callback will be called
// at most once. The move-only returned handle can be destroyed to cancel the
// callback.
// The callback may be used to delay the disruption by
// ensuring that any required side effects have taken place before it returns.
[[nodiscard]] CallbackHandle OnDisruptionStart(DisruptionCallback callback);
// Runs a callback when a disruption is no longer expected because it was
// cancelled or because there was a timeout. The callback will be called at
// most once. The move-only returned handle can be destroyed to cancel the
// callback.
[[nodiscard]] CallbackHandle OnDisruptionEnd(DisruptionCallback callback);
private:
absl::Status RunCallbacks(
CallbackManager& callback_manager, absl::string_view name,
absl::Duration delay,
std::source_location location = std::source_location::current());
mutable absl::Mutex disruption_mutex_;
absl::Time expect_disruption_until_ ABSL_GUARDED_BY(disruption_mutex_) =
absl::InfinitePast();
CallbackManager disruption_start_callbacks_;
CallbackManager disruption_end_callbacks_;
};
} // namespace safepower_agent
#endif // PRODUCTION_BORG_MGMT_NODE_PROXY_SAFEPOWER_SAFEPOWER_AGENT_DISRUPTION_MANAGER_H_