Remove unnecessary optional from scheduler.

PiperOrigin-RevId: 795275868
This commit is contained in:
Francis Tsui
2025-08-14 18:07:15 -07:00
committed by Copybara-Service
parent 59f46f4b5a
commit cff660eacf
27 changed files with 181 additions and 211 deletions
+3 -2
View File
@@ -26,10 +26,11 @@ class Timer {
//
// @param delay The amount of time in milliseconds relative to the current
// time that must elapse before the timer is signaled for the first
// time.
// time. If delay is negative, it will be treated as 0.
// @param period The period of the timer, in milliseconds. If this parameter
// is zero, the timer is signaled once. If this parameter is greater
// than zero, the timer is periodic.
// than zero, the timer is periodic. If period is negative, it will be
// treated as 0.
// @param callback The callback is called when timer is signaled
//
// @return Returns true if succeed, otherwise false is returned.
+6 -2
View File
@@ -29,8 +29,12 @@ bool TimerImpl::Start(int delay, int period,
return false;
}
delay_ = delay;
period_ = period;
if (delay < 0) {
delay = 0;
}
if (period < 0) {
period = 0;
}
internal_timer_ = api::ImplementationPlatform::CreateTimer();
if (!internal_timer_->Create(delay, period, std::move(callback))) {
LOG(INFO) << "Failed to create timer.";
-2
View File
@@ -33,8 +33,6 @@ class TimerImpl : public Timer {
bool FireNow() override;
private:
int delay_ = 0;
int period_ = 0;
std::unique_ptr<api::Timer> internal_timer_ = nullptr;
};
+4 -1
View File
@@ -24,7 +24,10 @@ namespace {
TEST(TimerImpl, TestCreateTimer) {
TimerImpl timer;
EXPECT_FALSE(timer.Start(-100, 0, nullptr));
EXPECT_TRUE(timer.Start(-100, 0, []() {}));
timer.Stop();
EXPECT_TRUE(timer.Start(0, -100, []() {}));
timer.Stop();
EXPECT_TRUE(timer.Start(100, 100, []() {}));
timer.Stop();
}
@@ -16,7 +16,6 @@
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
@@ -114,7 +113,7 @@ FakeNearbyShareCertificateStorage::GetPrivateCertificates() {
return private_certificates_;
}
std::optional<absl::Time>
absl::Time
FakeNearbyShareCertificateStorage::NextPublicCertificateExpirationTime() const {
return next_public_certificate_expiration_time_;
}
@@ -156,7 +155,7 @@ void FakeNearbyShareCertificateStorage::SetPublicCertificateIds(
}
void FakeNearbyShareCertificateStorage::SetNextPublicCertificateExpirationTime(
std::optional<absl::Time> time) {
absl::Time time) {
next_public_certificate_expiration_time_ = time;
}
@@ -17,7 +17,6 @@
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <vector>
@@ -109,8 +108,7 @@ class FakeNearbyShareCertificateStorage : public NearbyShareCertificateStorage {
bool, std::unique_ptr<nearby::sharing::proto::PublicCertificate>)>
callback) override;
std::vector<NearbySharePrivateCertificate> GetPrivateCertificates() override;
std::optional<absl::Time> NextPublicCertificateExpirationTime()
const override;
absl::Time NextPublicCertificateExpirationTime() const override;
void ReplacePrivateCertificates(
absl::Span<const NearbySharePrivateCertificate> private_certificates)
override;
@@ -123,7 +121,7 @@ class FakeNearbyShareCertificateStorage : public NearbyShareCertificateStorage {
void ClearPublicCertificates(ResultCallback callback) override;
void SetPublicCertificateIds(absl::Span<const absl::string_view> ids);
void SetNextPublicCertificateExpirationTime(std::optional<absl::Time> time);
void SetNextPublicCertificateExpirationTime(absl::Time time);
std::vector<PublicCertificateCallback>& get_public_certificates_callbacks() {
return get_public_certificates_callbacks_;
@@ -153,7 +151,7 @@ class FakeNearbyShareCertificateStorage : public NearbyShareCertificateStorage {
}
private:
std::optional<absl::Time> next_public_certificate_expiration_time_;
absl::Time next_public_certificate_expiration_time_ = absl::InfiniteFuture();
std::vector<std::string> public_certificate_ids_;
std::vector<NearbySharePrivateCertificate> private_certificates_;
std::vector<PublicCertificateCallback> get_public_certificates_callbacks_;
@@ -622,14 +622,14 @@ std::string NearbyShareCertificateManagerImpl::Dump() const {
return sstream.str();
}
std::optional<absl::Time>
absl::Time
NearbyShareCertificateManagerImpl::NextPrivateCertificateExpirationTime() {
std::optional<AccountManager::Account> account =
account_manager_.GetCurrentAccount();
// If the user is not logged in, there are no certs and we don't need to check
// for expiration.
if (!account.has_value()) {
return std::nullopt;
return absl::InfiniteFuture();
}
return certificate_storage_->NextPrivateCertificateExpirationTime(
NumExpectedPrivateCertificates());
@@ -745,18 +745,15 @@ void NearbyShareCertificateManagerImpl::ForceUploadPrivateCertificates() {
});
}
std::optional<absl::Time>
absl::Time
NearbyShareCertificateManagerImpl::NextPublicCertificateExpirationTime() {
std::optional<absl::Time> next_expiration_time =
absl::Time next_expiration_time =
certificate_storage_->NextPublicCertificateExpirationTime();
// Supposedly there are no store public certificates.
if (!next_expiration_time) return std::nullopt;
// To account for clock skew between devices, we accept public certificates
// that are slightly past their validity period. This conforms with the
// GmsCore implementation.
return *next_expiration_time +
return next_expiration_time +
kNearbySharePublicCertificateValidityBoundOffsetTolerance;
}
@@ -158,14 +158,15 @@ class NearbyShareCertificateManagerImpl
bool did_icon_change) override;
// Used by the private certificate expiration scheduler to determine the next
// private certificate expiration time. Returns base::Time::Min() if
// certificates are missing. This function never returns absl::nullopt.
std::optional<absl::Time> NextPrivateCertificateExpirationTime();
// private certificate expiration time. Returns InfinitePast() if
// certificates are missing. Returns InfiniteFuture() if the user is not
// logged in.
absl::Time NextPrivateCertificateExpirationTime();
// Used by the public certificate expiration scheduler to determine the next
// public certificate expiration time. Returns absl::nullopt if no public
// public certificate expiration time. Returns InfiniteFuture() if no public
// certificates are present, and no expiration event is scheduled.
std::optional<absl::Time> NextPublicCertificateExpirationTime();
absl::Time NextPublicCertificateExpirationTime();
// Clears all existing private certificates and regenerates new ones, then
// uploads them to the server, without triggering contacts update.
@@ -898,13 +898,13 @@ TEST_F(
Sync();
EXPECT_EQ(0, upload_scheduler_->num_immediate_requests());
std::optional<absl::Time> next_schedule_time =
absl::Time next_schedule_time =
scheduler_factory_.pref_name_to_expiration_instance()
.find(prefs::kNearbySharingSchedulerPrivateCertificateExpirationName)
->second.expiration_time_functor();
// Next expiration time is set to nullopt to disable the timer.
EXPECT_FALSE(next_schedule_time.has_value());
// Next expiration time is set to InfiniteFuture to disable the timer.
EXPECT_EQ(next_schedule_time, absl::InfiniteFuture());
}
TEST_F(NearbyShareCertificateManagerImplTest,
@@ -17,7 +17,6 @@
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <vector>
@@ -64,8 +63,10 @@ class NearbyShareCertificateStorage {
// Returns the next time a certificate expires or absl::InfinitePast() if
// there are fewer than `min_certs` present.
absl::Time NextPrivateCertificateExpirationTime(int min_certs);
virtual std::optional<absl::Time> NextPublicCertificateExpirationTime()
const = 0;
// Returns the time the next public certificate expires or
// absl::InfiniteFuture() if there are no public certificates present.
virtual absl::Time NextPublicCertificateExpirationTime() const = 0;
// Deletes existing private certificates and replaces them with
// |private_certificates|.
@@ -381,9 +381,9 @@ NearbyShareCertificateStorageImpl::GetPrivateCertificates() {
return certs;
}
std::optional<absl::Time>
absl::Time
NearbyShareCertificateStorageImpl::NextPublicCertificateExpirationTime() const {
if (public_certificate_expirations_.empty()) return std::nullopt;
if (public_certificate_expirations_.empty()) return absl::InfiniteFuture();
// |public_certificate_expirations_| is sorted by expiration date.
return public_certificate_expirations_.front().second;
@@ -19,7 +19,6 @@
#include <functional>
#include <memory>
#include <optional>
#include <queue>
#include <string>
#include <utility>
@@ -80,8 +79,7 @@ class NearbyShareCertificateStorageImpl : public NearbyShareCertificateStorage,
bool, std::unique_ptr<nearby::sharing::proto::PublicCertificate>)>
callback) override;
std::vector<NearbySharePrivateCertificate> GetPrivateCertificates() override;
std::optional<absl::Time> NextPublicCertificateExpirationTime()
const override;
absl::Time NextPublicCertificateExpirationTime() const override;
void ReplacePrivateCertificates(
absl::Span<const NearbySharePrivateCertificate> private_certificates)
override;
@@ -16,7 +16,6 @@
#include <stddef.h>
#include <optional>
#include <utility>
#include <vector>
@@ -42,15 +41,10 @@ void FakeNearbyShareScheduler::HandleResult(bool success) {
void FakeNearbyShareScheduler::Reschedule() { ++num_reschedule_calls_; }
std::optional<absl::Time> FakeNearbyShareScheduler::GetLastSuccessTime() const {
absl::Time FakeNearbyShareScheduler::GetLastSuccessTime() const {
return last_success_time_;
}
std::optional<absl::Duration>
FakeNearbyShareScheduler::GetTimeUntilNextRequest() const {
return time_until_next_request_;
}
bool FakeNearbyShareScheduler::IsWaitingForResult() const {
return is_waiting_for_result_;
}
@@ -64,16 +58,10 @@ void FakeNearbyShareScheduler::InvokeRequestCallback() {
NotifyOfRequest();
}
void FakeNearbyShareScheduler::SetLastSuccessTime(
std::optional<absl::Time> time) {
void FakeNearbyShareScheduler::SetLastSuccessTime(absl::Time time) {
last_success_time_ = time;
}
void FakeNearbyShareScheduler::SetTimeUntilNextRequest(
std::optional<absl::Duration> time_delta) {
time_until_next_request_ = time_delta;
}
void FakeNearbyShareScheduler::SetIsWaitingForResult(bool is_waiting) {
is_waiting_for_result_ = is_waiting;
}
@@ -17,7 +17,6 @@
#include <stddef.h>
#include <optional>
#include <vector>
#include "absl/time/time.h"
@@ -39,13 +38,11 @@ class FakeNearbyShareScheduler : public NearbyShareScheduler {
void MakeImmediateRequest() override;
void HandleResult(bool success) override;
void Reschedule() override;
std::optional<absl::Time> GetLastSuccessTime() const override;
std::optional<absl::Duration> GetTimeUntilNextRequest() const override;
absl::Time GetLastSuccessTime() const override;
bool IsWaitingForResult() const override;
size_t GetNumConsecutiveFailures() const override;
void SetLastSuccessTime(std::optional<absl::Time> time);
void SetTimeUntilNextRequest(std::optional<absl::Duration> time_delta);
void SetLastSuccessTime(absl::Time time);
void SetIsWaitingForResult(bool is_waiting);
void SetNumConsecutiveFailures(size_t num_failures);
@@ -63,8 +60,7 @@ class FakeNearbyShareScheduler : public NearbyShareScheduler {
size_t num_immediate_requests_ = 0;
size_t num_reschedule_calls_ = 0;
std::vector<bool> handled_results_;
std::optional<absl::Time> last_success_time_;
std::optional<absl::Duration> time_until_next_request_;
absl::Time last_success_time_ = absl::InfinitePast();
bool is_waiting_for_result_ = false;
size_t num_consecutive_failures_ = 0;
};
@@ -40,15 +40,13 @@ NearbyShareExpirationScheduler::NearbyShareExpirationScheduler(
NearbyShareExpirationScheduler::~NearbyShareExpirationScheduler() = default;
std::optional<absl::Duration>
NearbyShareExpirationScheduler::TimeUntilRecurringRequest(
absl::Duration NearbyShareExpirationScheduler::TimeUntilRecurringRequest(
absl::Time now) const {
std::optional<absl::Time> expiration_time = expiration_time_functor_();
if (!expiration_time.has_value()) return std::nullopt;
absl::Time expiration_time = expiration_time_functor_();
if (*expiration_time <= now) return absl::ZeroDuration();
if (expiration_time <= now) return absl::ZeroDuration();
return *expiration_time - now;
return expiration_time - now;
}
} // namespace sharing
@@ -32,7 +32,8 @@ namespace sharing {
// expiration time provided by the owner.
class NearbyShareExpirationScheduler : public NearbyShareSchedulerBase {
public:
using ExpirationTimeFunctor = std::function<std::optional<absl::Time>()>;
// Return InfiniteFuture() to stop scheduling.
using ExpirationTimeFunctor = std::function<absl::Time()>;
// |expiration_time_functor|: A function provided by the owner that returns
// the next expiration time.
@@ -47,8 +48,7 @@ class NearbyShareExpirationScheduler : public NearbyShareSchedulerBase {
~NearbyShareExpirationScheduler() override;
protected:
std::optional<absl::Duration> TimeUntilRecurringRequest(
absl::Time now) const override;
absl::Duration TimeUntilRecurringRequest(absl::Time now) const override;
ExpirationTimeFunctor expiration_time_functor_;
};
@@ -15,14 +15,12 @@
#include "sharing/scheduling/nearby_share_expiration_scheduler.h"
#include <memory>
#include <optional>
#include "gtest/gtest.h"
#include "absl/time/time.h"
#include "internal/test/fake_clock.h"
#include "sharing/internal/test/fake_context.h"
#include "sharing/internal/test/fake_preference_manager.h"
#include "sharing/scheduling/nearby_share_scheduler.h"
namespace nearby {
namespace sharing {
@@ -56,13 +54,13 @@ class NearbyShareExpirationSchedulerTest : public ::testing::Test {
fake_context_.fake_clock()->FastForward(delta);
}
std::optional<absl::Time> expiration_time_;
NearbyShareScheduler* scheduler() { return scheduler_.get(); }
absl::Time expiration_time_ = absl::InfiniteFuture();
NearbyShareExpirationScheduler* scheduler() { return scheduler_.get(); }
private:
nearby::FakePreferenceManager preference_manager_;
nearby::FakeContext fake_context_;
std::unique_ptr<NearbyShareScheduler> scheduler_ = nullptr;
std::unique_ptr<NearbyShareExpirationScheduler> scheduler_ = nullptr;
NearbyShareExpirationScheduler::ExpirationTimeFunctor callback_ = [&]() {
return expiration_time_;
};
@@ -75,7 +73,8 @@ TEST_F(NearbyShareExpirationSchedulerTest, ExpirationRequest) {
// the expiration time and the current time.
FastForward(absl::Minutes(5));
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(), *expiration_time_ - Now());
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
expiration_time_ - Now());
}
TEST_F(NearbyShareExpirationSchedulerTest, Reschedule) {
@@ -83,21 +82,22 @@ TEST_F(NearbyShareExpirationSchedulerTest, Reschedule) {
FastForward(absl::Minutes(5));
absl::Duration initial_expected_time_until_next_request =
*expiration_time_ - Now();
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(),
expiration_time_ - Now();
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
initial_expected_time_until_next_request);
// The expiration time suddenly changes.
expiration_time_ = *expiration_time_ + absl::Hours(48);
expiration_time_ = expiration_time_ + absl::Hours(48);
scheduler()->Reschedule();
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(),
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
initial_expected_time_until_next_request + absl::Hours(48));
}
TEST_F(NearbyShareExpirationSchedulerTest, NullExpirationTime) {
expiration_time_.reset();
expiration_time_ = absl::InfiniteFuture();
scheduler()->Start();
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(), std::nullopt);
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
absl::InfiniteDuration());
}
} // namespace
@@ -14,7 +14,6 @@
#include "sharing/scheduling/nearby_share_on_demand_scheduler.h"
#include <optional>
#include <utility>
#include "absl/strings/string_view.h"
@@ -38,9 +37,9 @@ NearbyShareOnDemandScheduler::NearbyShareOnDemandScheduler(
NearbyShareOnDemandScheduler::~NearbyShareOnDemandScheduler() = default;
std::optional<absl::Duration>
NearbyShareOnDemandScheduler::TimeUntilRecurringRequest(absl::Time now) const {
return std::nullopt;
absl::Duration NearbyShareOnDemandScheduler::TimeUntilRecurringRequest(
absl::Time now) const {
return absl::InfiniteDuration();
}
} // namespace sharing
@@ -15,8 +15,6 @@
#ifndef THIRD_PARTY_NEARBY_SHARING_SCHEDULING_NEARBY_SHARE_ON_DEMAND_SCHEDULER_H_
#define THIRD_PARTY_NEARBY_SHARING_SCHEDULING_NEARBY_SHARE_ON_DEMAND_SCHEDULER_H_
#include <optional>
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "sharing/internal/api/preference_manager.h"
@@ -40,9 +38,8 @@ class NearbyShareOnDemandScheduler : public NearbyShareSchedulerBase {
~NearbyShareOnDemandScheduler() override;
private:
// Return absl::nullopt so as not to schedule recurring requests.
std::optional<absl::Duration> TimeUntilRecurringRequest(
absl::Time now) const override;
// Return `absl::InfiniteDuration` so as not to schedule recurring requests.
absl::Duration TimeUntilRecurringRequest(absl::Time now) const override;
};
} // namespace sharing
@@ -17,9 +17,9 @@
#include <memory>
#include "gtest/gtest.h"
#include "absl/time/time.h"
#include "sharing/internal/test/fake_context.h"
#include "sharing/internal/test/fake_preference_manager.h"
#include "sharing/scheduling/nearby_share_scheduler.h"
namespace nearby {
namespace sharing {
@@ -41,17 +41,18 @@ class NearbyShareOnDemandSchedulerTest : public ::testing::Test {
nullptr);
}
NearbyShareScheduler* scheduler() { return scheduler_.get(); }
NearbyShareOnDemandScheduler* scheduler() { return scheduler_.get(); }
private:
nearby::FakePreferenceManager preference_manager_;
FakeContext fake_context_;
std::unique_ptr<NearbyShareScheduler> scheduler_;
std::unique_ptr<NearbyShareOnDemandScheduler> scheduler_;
};
TEST_F(NearbyShareOnDemandSchedulerTest, NoRecurringRequest) {
scheduler()->Start();
EXPECT_FALSE(scheduler()->GetTimeUntilNextRequest());
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
absl::InfiniteDuration());
}
} // namespace
@@ -15,7 +15,6 @@
#include "sharing/scheduling/nearby_share_periodic_scheduler.h"
#include <algorithm>
#include <optional>
#include <utility>
#include "absl/strings/string_view.h"
@@ -41,17 +40,10 @@ NearbySharePeriodicScheduler::NearbySharePeriodicScheduler(
NearbySharePeriodicScheduler::~NearbySharePeriodicScheduler() = default;
std::optional<absl::Duration>
absl::Duration
NearbySharePeriodicScheduler::TimeUntilRecurringRequest(absl::Time now) const {
std::optional<absl::Time> last_success_time = GetLastSuccessTime();
// Immediately run a first-time request.
if (!last_success_time.has_value()) return absl::ZeroDuration();
absl::Duration time_elapsed_since_last_success = now - *last_success_time;
return std::max(absl::ZeroDuration(),
request_period_ - time_elapsed_since_last_success);
request_period_ - (now - GetLastSuccessTime()));
}
} // namespace sharing
@@ -15,8 +15,6 @@
#ifndef THIRD_PARTY_NEARBY_SHARING_SCHEDULING_NEARBY_SHARE_PERIODIC_SCHEDULER_H_
#define THIRD_PARTY_NEARBY_SHARING_SCHEDULING_NEARBY_SHARE_PERIODIC_SCHEDULER_H_
#include <optional>
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "sharing/internal/api/preference_manager.h"
@@ -47,8 +45,7 @@ class NearbySharePeriodicScheduler : public NearbyShareSchedulerBase {
private:
// Returns the time until the next periodic request using the time since
// the last success. Immediately runs a first-time periodic request.
std::optional<absl::Duration> TimeUntilRecurringRequest(
absl::Time now) const override;
absl::Duration TimeUntilRecurringRequest(absl::Time now) const override;
absl::Duration request_period_;
};
@@ -15,14 +15,12 @@
#include "sharing/scheduling/nearby_share_periodic_scheduler.h"
#include <memory>
#include <optional>
#include "gtest/gtest.h"
#include "absl/time/time.h"
#include "internal/test/fake_clock.h"
#include "sharing/internal/test/fake_context.h"
#include "sharing/internal/test/fake_preference_manager.h"
#include "sharing/scheduling/nearby_share_scheduler.h"
namespace nearby {
namespace sharing {
@@ -52,12 +50,12 @@ class NearbySharePeriodicSchedulerTest : public ::testing::Test {
fake_context_.fake_clock()->FastForward(delta);
}
NearbyShareScheduler* scheduler() { return scheduler_.get(); }
NearbySharePeriodicScheduler* scheduler() { return scheduler_.get(); }
private:
nearby::FakePreferenceManager preference_manager_;
FakeContext fake_context_;
std::unique_ptr<NearbyShareScheduler> scheduler_;
std::unique_ptr<NearbySharePeriodicScheduler> scheduler_;
};
TEST_F(NearbySharePeriodicSchedulerTest, PeriodicRequest) {
@@ -66,10 +64,11 @@ TEST_F(NearbySharePeriodicSchedulerTest, PeriodicRequest) {
// Immediately runs a first-time periodic request.
scheduler()->Start();
std::optional<absl::Duration> time_until_next_request =
scheduler()->GetTimeUntilNextRequest();
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(), absl::ZeroDuration());
FastForward(*time_until_next_request);
absl::Duration time_until_next_request =
scheduler()->GetTimeUntilNextRequestForTest();
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
absl::ZeroDuration());
FastForward(time_until_next_request);
scheduler()->HandleResult(/*success=*/true);
EXPECT_EQ(scheduler()->GetLastSuccessTime(), Now());
@@ -77,7 +76,7 @@ TEST_F(NearbySharePeriodicSchedulerTest, PeriodicRequest) {
absl::Duration elapsed_time = absl::Minutes(1);
FastForward(elapsed_time);
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(),
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
kTestRequestPeriod - elapsed_time);
}
+2 -7
View File
@@ -19,7 +19,6 @@
#include <atomic>
#include <functional>
#include <optional>
#include "absl/time/time.h"
@@ -58,12 +57,8 @@ class NearbyShareScheduler {
virtual void Reschedule() = 0;
// Returns the time of the last known successful request. If no request has
// succeeded, absl::nullopt is returned.
virtual std::optional<absl::Time> GetLastSuccessTime() const = 0;
// Returns the time until the next scheduled request. Returns std::nullopt if
// there is no request scheduled.
virtual std::optional<absl::Duration> GetTimeUntilNextRequest() const = 0;
// succeeded, `absl::InfinitePast` is returned.
virtual absl::Time GetLastSuccessTime() const = 0;
// Returns true after the |callback_| has been alerted of a request but before
// HandleResult() is invoked.
@@ -123,39 +123,39 @@ void NearbyShareSchedulerBase::Reschedule() {
timer_->Stop();
std::optional<absl::Duration> delay = GetTimeUntilNextRequest();
if (!delay.has_value()) {
absl::Duration delay = GetTimeUntilNextRequest();
if (delay == absl::InfiniteDuration()) {
LOG(INFO) << "Task \"" << pref_name_ << "\"" << " not scheduled";
} else {
int64_t delay_milliseconds = absl::ToInt64Milliseconds(*delay);
LOG(INFO) << "Task \"" << pref_name_ << "\"" << " scheduled in " << *delay;
int64_t delay_milliseconds = absl::ToInt64Milliseconds(delay);
LOG(INFO) << "Task \"" << pref_name_ << "\"" << " scheduled in " << delay;
timer_->Start(delay_milliseconds, /*period=*/0,
[this]() { OnTimerFired(); });
}
PrintSchedulerState(delay);
}
std::optional<absl::Time> NearbyShareSchedulerBase::GetLastSuccessTime() const {
absl::Time NearbyShareSchedulerBase::GetLastSuccessTime() const {
std::optional<int64_t> pref_value =
preference_manager_.GetDictionaryInt64Value(
pref_name_, SchedulerFields::kLastSuccessTimeKeyName);
if (!pref_value.has_value()) {
return std::nullopt;
return absl::InfinitePast();
}
return absl::FromUnixNanos(pref_value.value());
}
std::optional<absl::Duration>
NearbyShareSchedulerBase::GetTimeUntilNextRequest() const {
if (!is_running() || IsWaitingForResult()) return std::nullopt;
absl::Duration NearbyShareSchedulerBase::GetTimeUntilNextRequest() const {
if (!is_running() || IsWaitingForResult()) return absl::InfiniteDuration();
if (HasPendingImmediateRequest()) return absl::ZeroDuration();
absl::Time now = clock_->Now();
// Recover from failures using exponential backoff strategy if necessary.
std::optional<absl::Duration> time_until_retry = TimeUntilRetry(now);
if (time_until_retry) return time_until_retry;
absl::Duration time_until_retry = TimeUntilRetry(now);
if (time_until_retry != absl::InfiniteDuration())
return time_until_retry;
// Schedule the periodic request if applicable.
return TimeUntilRecurringRequest(now);
@@ -199,12 +199,12 @@ void NearbyShareSchedulerBase::OnInternetConnectivityChanged(
Reschedule();
}
std::optional<absl::Time> NearbyShareSchedulerBase::GetLastAttemptTime() const {
absl::Time NearbyShareSchedulerBase::GetLastAttemptTime() const {
std::optional<int64_t> pref_value =
preference_manager_.GetDictionaryInt64Value(
pref_name_, SchedulerFields::kLastAttemptTimeKeyName);
if (!pref_value.has_value()) {
return std::nullopt;
return absl::InfinitePast();
}
return absl::FromUnixNanos(pref_value.value());
}
@@ -253,12 +253,11 @@ void NearbyShareSchedulerBase::SetIsWaitingForResult(
is_waiting_for_result);
}
std::optional<absl::Duration> NearbyShareSchedulerBase::TimeUntilRetry(
absl::Time now) const {
if (!retry_failures_) return std::nullopt;
absl::Duration NearbyShareSchedulerBase::TimeUntilRetry(absl::Time now) const {
if (!retry_failures_) return absl::InfiniteDuration();
size_t num_failures = GetNumConsecutiveFailures();
if (num_failures == 0) return std::nullopt;
if (num_failures == 0) return absl::InfiniteDuration();
// The exponential back off is
//
@@ -268,7 +267,7 @@ std::optional<absl::Duration> NearbyShareSchedulerBase::TimeUntilRetry(
absl::Duration delay =
std::min(kMaxRetryDelay, kBaseRetryDelay * (1 << (num_failures - 1)));
absl::Duration time_elapsed_since_last_attempt = now - *GetLastAttemptTime();
absl::Duration time_elapsed_since_last_attempt = now - GetLastAttemptTime();
return std::max(absl::ZeroDuration(),
delay - time_elapsed_since_last_attempt);
@@ -291,34 +290,34 @@ void NearbyShareSchedulerBase::OnTimerFired() {
}
void NearbyShareSchedulerBase::PrintSchedulerState(
std::optional<absl::Duration> time_until_next_request) const {
absl::Duration time_until_next_request) const {
if (!VLOG_IS_ON(1)) {
return;
}
std::optional<absl::Time> last_attempt_time = GetLastAttemptTime();
std::optional<absl::Time> last_success_time = GetLastSuccessTime();
absl::Time last_attempt_time = GetLastAttemptTime();
absl::Time last_success_time = GetLastSuccessTime();
std::stringstream ss;
ss << "State of Nearby Share scheduler \"" << pref_name_ << "\":"
<< "\n Last attempt time: ";
if (last_attempt_time) {
if (last_attempt_time != absl::InfinitePast()) {
ss << nearby::utils::TimeFormatShortDateAndTimeWithTimeZone(
*last_attempt_time);
last_attempt_time);
} else {
ss << "Never";
}
ss << "\n Last success time: ";
if (last_success_time) {
if (last_success_time != absl::InfinitePast()) {
ss << nearby::utils::TimeFormatShortDateAndTimeWithTimeZone(
*last_success_time);
last_success_time);
} else {
ss << "Never";
}
ss << "\n Time until next request: ";
if (time_until_next_request) {
ss << *time_until_next_request;
if (time_until_next_request != absl::InfiniteDuration()) {
ss << time_until_next_request;
} else {
ss << "Never";
}
@@ -18,7 +18,6 @@
#include <stddef.h>
#include <memory>
#include <optional>
#include <string>
#include "absl/strings/string_view.h"
@@ -55,11 +54,14 @@ class NearbyShareSchedulerBase : public NearbyShareScheduler {
void MakeImmediateRequest() override;
void HandleResult(bool success) override;
void Reschedule() override;
std::optional<absl::Time> GetLastSuccessTime() const override;
std::optional<absl::Duration> GetTimeUntilNextRequest() const override;
absl::Time GetLastSuccessTime() const override;
bool IsWaitingForResult() const override;
size_t GetNumConsecutiveFailures() const override;
absl::Duration GetTimeUntilNextRequestForTest() const {
return GetTimeUntilNextRequest();
}
protected:
// |context|: Nearby context, holding nearby common components.
// |retry_failures|: Whether or not automatically retry failures using
@@ -76,16 +78,22 @@ class NearbyShareSchedulerBase : public NearbyShareScheduler {
absl::string_view pref_name, OnRequestCallback callback);
// The time to wait until the next regularly recurring request.
virtual std::optional<absl::Duration> TimeUntilRecurringRequest(
// Returns `InfiniteDuration` if there is no recurring request scheduled.
virtual absl::Duration TimeUntilRecurringRequest(
absl::Time now) const = 0;
void OnStart() override;
void OnStop() override;
// Returns the time until the next scheduled request. Returns
// `InfiniteDuration` if there is no request scheduled.
absl::Duration GetTimeUntilNextRequest() const;
private:
void OnInternetConnectivityChanged(bool is_internet_connected);
std::optional<absl::Time> GetLastAttemptTime() const;
// Get the last attempt time from prefs. Returns `InfinitePast` if the last
// attempt time is not set.
absl::Time GetLastAttemptTime() const;
bool HasPendingImmediateRequest() const;
// Set and persist scheduling data in prefs.
@@ -96,17 +104,16 @@ class NearbyShareSchedulerBase : public NearbyShareScheduler {
void SetIsWaitingForResult(bool is_waiting_for_result);
// 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<absl::Duration> TimeUntilRetry(absl::Time now) const;
// `InfiniteDuration` if there is no failure to retry or if failure retry is
// not enabled for the scheduler.
absl::Duration TimeUntilRetry(absl::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(
std::optional<absl::Duration> time_until_next_request) const;
void PrintSchedulerState(absl::Duration time_until_next_request) const;
nearby::ConnectivityManager* const connectivity_manager_;
nearby::sharing::api::PreferenceManager& preference_manager_;
@@ -25,6 +25,7 @@
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "internal/test/fake_clock.h"
#include "sharing/internal/public/context.h"
#include "sharing/internal/test/fake_context.h"
#include "sharing/internal/test/fake_preference_manager.h"
#include "sharing/scheduling/nearby_share_scheduler.h"
@@ -45,12 +46,13 @@ constexpr absl::Duration kTestTimeUntilRecurringRequest = absl::Minutes(120);
class NearbyShareSchedulerBaseForTest : public NearbyShareSchedulerBase {
public:
NearbyShareSchedulerBaseForTest(
Context* context,
PreferenceManager& preference_manager,
std::optional<absl::Duration> time_until_recurring_request,
bool retry_failures, bool require_connectivity,
absl::string_view pref_name, OnRequestCallback callback)
NearbyShareSchedulerBaseForTest(Context* context,
PreferenceManager& preference_manager,
absl::Duration time_until_recurring_request,
bool retry_failures,
bool require_connectivity,
absl::string_view pref_name,
OnRequestCallback callback)
: NearbyShareSchedulerBase(context, preference_manager, retry_failures,
require_connectivity, pref_name,
std::move(callback)),
@@ -58,13 +60,11 @@ class NearbyShareSchedulerBaseForTest : public NearbyShareSchedulerBase {
~NearbyShareSchedulerBaseForTest() override = default;
private:
std::optional<absl::Duration> TimeUntilRecurringRequest(
absl::Time now) const override {
absl::Duration TimeUntilRecurringRequest(absl::Time now) const override {
return time_until_recurring_request_;
}
std::optional<absl::Duration> time_until_recurring_request_;
absl::Duration time_until_recurring_request_;
};
class NearbyShareSchedulerBaseTest : public ::testing::Test {
@@ -73,14 +73,11 @@ class NearbyShareSchedulerBaseTest : public ::testing::Test {
~NearbyShareSchedulerBaseTest() override = default;
void SetUp() override {
preference_manager_.Remove(kTestPrefName);
}
void SetUp() override { preference_manager_.Remove(kTestPrefName); }
void CreateScheduler(
bool retry_failures, bool require_connectivity,
std::optional<absl::Duration> time_until_recurring_request =
kTestTimeUntilRecurringRequest) {
void CreateScheduler(bool retry_failures, bool require_connectivity,
absl::Duration time_until_recurring_request =
kTestTimeUntilRecurringRequest) {
scheduler_ = std::make_unique<NearbyShareSchedulerBaseForTest>(
&fake_context_, preference_manager_, time_until_recurring_request,
retry_failures, require_connectivity, kTestPrefName, callback_);
@@ -106,14 +103,15 @@ class NearbyShareSchedulerBaseTest : public ::testing::Test {
void RunPendingRequest() {
EXPECT_FALSE(scheduler_->IsWaitingForResult());
std::optional<absl::Duration> time_until_next_request =
scheduler_->GetTimeUntilNextRequest();
scheduler_->GetTimeUntilNextRequestForTest();
ASSERT_TRUE(time_until_next_request);
FastForward(*time_until_next_request);
}
void FinishPendingRequest(bool success) {
EXPECT_TRUE(scheduler_->IsWaitingForResult());
EXPECT_FALSE(scheduler_->GetTimeUntilNextRequest().has_value());
EXPECT_EQ(scheduler_->GetTimeUntilNextRequestForTest(),
absl::InfiniteDuration());
size_t num_failures = scheduler_->GetNumConsecutiveFailures();
std::optional<absl::Time> last_success_time =
scheduler_->GetLastSuccessTime();
@@ -126,18 +124,16 @@ class NearbyShareSchedulerBaseTest : public ::testing::Test {
success ? std::make_optional<absl::Time>(Now()) : last_success_time);
}
absl::Time Now() const {
return fake_context_.GetClock()->Now();
}
absl::Time Now() const { return fake_context_.GetClock()->Now(); }
size_t on_request_call_count() const { return on_request_call_count_; }
NearbyShareScheduler* scheduler() { return scheduler_.get(); }
NearbyShareSchedulerBaseForTest* scheduler() { return scheduler_.get(); }
protected:
nearby::FakePreferenceManager preference_manager_;
nearby::FakeContext fake_context_;
size_t on_request_call_count_ = 0;
std::unique_ptr<NearbyShareScheduler> scheduler_;
std::unique_ptr<NearbyShareSchedulerBaseForTest> scheduler_;
NearbyShareScheduler::OnRequestCallback callback_ = [&]() {
++on_request_call_count_;
};
@@ -147,7 +143,7 @@ TEST_F(NearbyShareSchedulerBaseTest, ImmediateRequest) {
CreateScheduler(/*retry_failures=*/true, /*require_connectivity=*/true);
StartScheduling();
scheduler()->MakeImmediateRequest();
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(), kZeroTimeDuration);
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(), kZeroTimeDuration);
ASSERT_NO_FATAL_FAILURE(RunPendingRequest());
EXPECT_EQ(on_request_call_count(), 1u);
FinishPendingRequest(/*success=*/true);
@@ -156,42 +152,46 @@ TEST_F(NearbyShareSchedulerBaseTest, ImmediateRequest) {
TEST_F(NearbyShareSchedulerBaseTest, RecurringRequest) {
CreateScheduler(/*retry_failures=*/true, /*require_connectivity=*/true);
StartScheduling();
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(),
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
kTestTimeUntilRecurringRequest);
ASSERT_NO_FATAL_FAILURE(RunPendingRequest());
FinishPendingRequest(/*success=*/true);
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(),
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
kTestTimeUntilRecurringRequest);
}
TEST_F(NearbyShareSchedulerBaseTest, NoRecurringRequest) {
// The flavor of the schedule does not schedule recurring requests.
CreateScheduler(/*retry_failures=*/true, /*require_connectivity=*/true,
/*time_until_recurring_request=*/std::nullopt);
/*time_until_recurring_request=*/absl::InfiniteDuration());
StartScheduling();
EXPECT_FALSE(scheduler()->GetTimeUntilNextRequest());
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
absl::InfiniteDuration());
scheduler()->MakeImmediateRequest();
ASSERT_NO_FATAL_FAILURE(RunPendingRequest());
FinishPendingRequest(/*success=*/true);
EXPECT_FALSE(scheduler()->GetTimeUntilNextRequest());
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
absl::InfiniteDuration());
}
TEST_F(NearbyShareSchedulerBaseTest, SchedulingNotStarted) {
CreateScheduler(/*retry_failures=*/true, /*require_connectivity=*/true);
EXPECT_FALSE(scheduler()->is_running());
EXPECT_FALSE(scheduler()->GetTimeUntilNextRequest());
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
absl::InfiniteDuration());
EXPECT_FALSE(scheduler()->IsWaitingForResult());
// Request remains pending until scheduling starts.
scheduler()->MakeImmediateRequest();
EXPECT_FALSE(scheduler()->is_running());
EXPECT_FALSE(scheduler()->GetTimeUntilNextRequest());
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
absl::InfiniteDuration());
EXPECT_FALSE(scheduler()->IsWaitingForResult());
StartScheduling();
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(), kZeroTimeDuration);
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(), kZeroTimeDuration);
EXPECT_FALSE(scheduler()->IsWaitingForResult());
}
@@ -208,7 +208,7 @@ TEST_F(NearbyShareSchedulerBaseTest, DoNotRetryFailures) {
// Failure is not automatically retried; the recurring request is re-scheduled
// instead.
EXPECT_EQ(kTestTimeUntilRecurringRequest,
scheduler()->GetTimeUntilNextRequest());
scheduler()->GetTimeUntilNextRequestForTest());
ASSERT_NO_FATAL_FAILURE(RunPendingRequest());
EXPECT_EQ(on_request_call_count(), 2u);
@@ -228,12 +228,12 @@ TEST_F(NearbyShareSchedulerBaseTest, FailureRetry) {
ASSERT_NO_FATAL_FAILURE(RunPendingRequest());
EXPECT_EQ(on_request_call_count(), num_failures + 1);
FinishPendingRequest(/*success=*/false);
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(),
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
std::min(kMaxRetryDuration,
kBaseRetryDuration * expected_backoff_factor));
expected_backoff_factor *= 2;
++num_failures;
} while (*scheduler()->GetTimeUntilNextRequest() != kMaxRetryDuration);
} while (scheduler()->GetTimeUntilNextRequestForTest() != kMaxRetryDuration);
ASSERT_NO_FATAL_FAILURE(RunPendingRequest());
EXPECT_EQ(on_request_call_count(), num_failures + 1);
@@ -255,7 +255,7 @@ TEST_F(NearbyShareSchedulerBaseTest,
FinishPendingRequest(/*success=*/false);
EXPECT_EQ(std::min(kMaxRetryDuration,
kBaseRetryDuration * expected_backoff_factor),
scheduler()->GetTimeUntilNextRequest());
scheduler()->GetTimeUntilNextRequestForTest());
expected_backoff_factor *= 2;
++num_failures;
} while (num_failures < 3);
@@ -264,11 +264,11 @@ TEST_F(NearbyShareSchedulerBaseTest,
// the retry strategy using the next backoff.
EXPECT_EQ(scheduler()->GetNumConsecutiveFailures(), num_failures);
scheduler()->MakeImmediateRequest();
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(), kZeroTimeDuration);
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(), kZeroTimeDuration);
ASSERT_NO_FATAL_FAILURE(RunPendingRequest());
EXPECT_EQ(on_request_call_count(), num_failures + 1);
FinishPendingRequest(/*success=*/false);
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(),
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
std::min(kMaxRetryDuration,
kBaseRetryDuration * expected_backoff_factor));
EXPECT_EQ(scheduler()->GetNumConsecutiveFailures(), num_failures + 1);
@@ -279,15 +279,17 @@ TEST_F(NearbyShareSchedulerBaseTest, StopScheduling_BeforeTimerFires) {
scheduler()->MakeImmediateRequest();
StartScheduling();
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(), kZeroTimeDuration);
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(), kZeroTimeDuration);
StopScheduling();
EXPECT_FALSE(scheduler()->GetTimeUntilNextRequest());
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
absl::InfiniteDuration());
// Timer is still fired but owner is not notified.
FastForward(kZeroTimeDuration);
EXPECT_FALSE(scheduler()->IsWaitingForResult());
EXPECT_FALSE(scheduler()->GetTimeUntilNextRequest());
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
absl::InfiniteDuration());
// Scheduling restarts and pending task is rescheduled.
StartScheduling();
@@ -310,7 +312,8 @@ TEST_F(NearbyShareSchedulerBaseTest, StopScheduling_BeforeResultIsHandled) {
// Although scheduling is stopped, the result can still be handled. No further
// requests will be scheduled though.
FinishPendingRequest(/*success=*/true);
EXPECT_FALSE(scheduler()->GetTimeUntilNextRequest());
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(),
absl::InfiniteDuration());
}
TEST_F(NearbyShareSchedulerBaseTest, RestoreRequest_InProgress) {
@@ -326,7 +329,7 @@ TEST_F(NearbyShareSchedulerBaseTest, RestoreRequest_InProgress) {
// in-progress request at the time of shutdown.
CreateScheduler(/*retry_failures=*/true, /*require_connectivity=*/true);
StartScheduling();
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(), kZeroTimeDuration);
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(), kZeroTimeDuration);
EXPECT_FALSE(scheduler()->IsWaitingForResult());
ASSERT_NO_FATAL_FAILURE(RunPendingRequest());
EXPECT_EQ(on_request_call_count(), 2u);
@@ -337,14 +340,14 @@ TEST_F(NearbyShareSchedulerBaseTest, RestoreRequest_Pending_Immediate) {
CreateScheduler(/*retry_failures=*/true, /*require_connectivity=*/true);
scheduler()->MakeImmediateRequest();
StartScheduling();
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(), kZeroTimeDuration);
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(), kZeroTimeDuration);
DestroyScheduler();
// On startup, set a pending immediate request because there was a pending
// immediate request at the time of shutdown.
CreateScheduler(/*retry_failures=*/true, /*require_connectivity=*/true);
StartScheduling();
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(), kZeroTimeDuration);
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(), kZeroTimeDuration);
EXPECT_FALSE(scheduler()->IsWaitingForResult());
ASSERT_NO_FATAL_FAILURE(RunPendingRequest());
EXPECT_EQ(on_request_call_count(), 1u);
@@ -363,7 +366,7 @@ TEST_F(NearbyShareSchedulerBaseTest, RestoreRequest_Pending_FailureRetry) {
FinishPendingRequest(/*success=*/false);
}
absl::Duration initial_time_until_next_request =
*scheduler()->GetTimeUntilNextRequest();
scheduler()->GetTimeUntilNextRequestForTest();
EXPECT_EQ(initial_time_until_next_request, 4 * kBaseRetryDuration);
DestroyScheduler();
@@ -374,7 +377,7 @@ TEST_F(NearbyShareSchedulerBaseTest, RestoreRequest_Pending_FailureRetry) {
CreateScheduler(/*retry_failures=*/true, /*require_connectivity=*/true);
StartScheduling();
EXPECT_FALSE(scheduler()->IsWaitingForResult());
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(), absl::Seconds(0));
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(), absl::Seconds(0));
EXPECT_EQ(scheduler()->GetNumConsecutiveFailures(), 3u);
ASSERT_NO_FATAL_FAILURE(RunPendingRequest());
EXPECT_EQ(on_request_call_count(), 4u);
@@ -400,11 +403,10 @@ TEST_F(NearbyShareSchedulerBaseTest, RestoreSchedulingData) {
CreateScheduler(/*retry_failures=*/true, /*require_connectivity=*/true);
StartScheduling();
EXPECT_EQ(scheduler()->GetLastSuccessTime(), expected_last_success_time);
EXPECT_EQ(scheduler()->GetTimeUntilNextRequest(), absl::Seconds(0));
EXPECT_EQ(scheduler()->GetTimeUntilNextRequestForTest(), absl::Seconds(0));
EXPECT_EQ(scheduler()->GetNumConsecutiveFailures(), 1u);
}
TEST_F(NearbyShareSchedulerBaseTest, InternetConnectivityChange) {
fake_context_.fake_connectivity_manager()->SetInternetConnected(false);
CreateScheduler(/*retry_failures=*/true, /*require_connectivity=*/true);