chromium/chromeos/ash/components/nearby/common/scheduling/nearby_scheduler_base.h

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMEOS_ASH_COMPONENTS_NEARBY_COMMON_SCHEDULING_NEARBY_SCHEDULER_BASE_H_
#define CHROMEOS_ASH_COMPONENTS_NEARBY_COMMON_SCHEDULING_NEARBY_SCHEDULER_BASE_H_

#include <memory>
#include <optional>
#include <string>

#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chromeos/ash/components/nearby/common/scheduling/nearby_scheduler.h"
#include "components/cross_device/logging/logging.h"
#include "services/network/public/cpp/network_connection_tracker.h"

namespace base {
class Clock;
}  // namespace base

class PrefService;

namespace ash::nearby {

// A base NearbyScheduler implementation that persists scheduling data.
// Requests made before scheduling has started, while another attempt is in
// progress, or while offline are cached and rescheduled as soon as possible.
// Likewise, when the scheduler is stopped or destroyed, scheduling data is
// persisted and restored when the scheduler is restarted or recreated,
// respectively.
//
// If automatic failure retry is enabled, all failed attempts follow an
// exponential backoff retry strategy.
//
// The scheduler waits until the device is online before notifying the owner if
// network connectivity is required.
//
// Derived classes must override TimeUntilRecurringRequest() to establish the
// desired recurring request behavior of the scheduler.
class NearbySchedulerBase
    : public NearbyScheduler,
      public network::NetworkConnectionTracker::NetworkConnectionObserver {
 public:
  ~NearbySchedulerBase() override;

 protected:
  // |retry_failures|: Whether or not automatically retry failures using
  //     exponential backoff strategy.
  // |require_connectivity|: If true, the scheduler will not alert the owner of
  //     a request until network connectivity is established.
  // |pref_name|: The dictionary pref name used to persist scheduling data. Make
  //     sure to register this pref name before creating the scheduler.
  // |pref_service|: The pref service used to persist scheduling data.
  // |callback|: The function invoked to alert the owner that a request is due.
  // |logging_feature|: The feature for CD_LOG to tag logs with.
  // |clock|: The clock used to determine timer delays.
  NearbySchedulerBase(bool retry_failures,
                      bool require_connectivity,
                      const std::string& pref_name,
                      PrefService* pref_service,
                      OnRequestCallback callback,
                      Feature logging_feature,
                      const base::Clock* clock);

  // The time to wait until the next regularly recurring request.
  virtual std::optional<base::TimeDelta> TimeUntilRecurringRequest(
      base::Time now) const = 0;

  // NearbyScheduler:
  void MakeImmediateRequest() override;
  void HandleResult(bool success) override;
  void Reschedule() override;
  std::optional<base::Time> GetLastSuccessTime() const override;
  std::optional<base::TimeDelta> GetTimeUntilNextRequest() const override;
  bool IsWaitingForResult() const override;
  size_t GetNumConsecutiveFailures() const override;
  void OnStart() override;
  void OnStop() override;

  // network::NetworkConnectionTracker::NetworkConnectionObserver:
  void OnConnectionChanged(network::mojom::ConnectionType type) override;

  std::optional<base::Time> GetLastAttemptTime() const;
  bool HasPendingImmediateRequest() const;

  // Set and persist scheduling data in prefs.
  void SetLastAttemptTime(base::Time last_attempt_time);
  void SetLastSuccessTime(base::Time last_success_time);
  void SetNumConsecutiveFailures(size_t num_failures);
  void SetHasPendingImmediateRequest(bool has_pending_immediate_request);
  void SetIsWaitingForResult(bool is_waiting_for_result);

  // On startup, set a pending immediate request if the pref service indicates
  // that there was an in-progress request or a pending immediate request at the
  // time of shutdown.
  void InitializePersistedRequest();

  // The amount of time to wait until the next automatic failure retry. Returns
  // std::nullopt if there is no failure to retry or if failure retry is not
  // enabled for the scheduler.
  std::optional<base::TimeDelta> TimeUntilRetry(base::Time now) const;

  // Notifies the owner that a request is ready. Early returns if not online and
  // the scheduler requires connectivity; the attempt is rescheduled when
  // connectivity is restored.
  void OnTimerFired();

  void PrintSchedulerState() const;

  bool retry_failures_;
  bool require_connectivity_;
  std::string pref_name_;
  raw_ptr<PrefService> pref_service_ = nullptr;
  Feature logging_feature_;
  raw_ptr<const base::Clock> clock_ = nullptr;
  base::OneShotTimer timer_;
};

}  // namespace ash::nearby

#endif  // CHROMEOS_ASH_COMPONENTS_NEARBY_COMMON_SCHEDULING_NEARBY_SCHEDULER_BASE_H_