Commit 2e311ace authored by Mila Green's avatar Mila Green Committed by Chromium LUCI CQ

Updater: Set jitter for the client in an external constant.

Bug: 1144151
Change-Id: Ie836759be36fc86e9a3b15b2ee2b6c086bc2f890
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2625227Reviewed-by: default avatarJoshua Pawlicki <waffles@chromium.org>
Commit-Queue: Mila Green <milagreen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843112}
parent b5e55c19
...@@ -332,7 +332,6 @@ if (is_win || is_mac) { ...@@ -332,7 +332,6 @@ if (is_win || is_mac) {
"test/server.cc", "test/server.cc",
"test/server.h", "test/server.h",
"unittest_util_unittest.cc", "unittest_util_unittest.cc",
"update_service_internal_impl_unittest.cc",
"update_service_unittest.cc", "update_service_unittest.cc",
"updater_unittest.cc", "updater_unittest.cc",
] ]
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include "chrome/updater/configurator.h" #include "chrome/updater/configurator.h"
#include <utility> #include <utility>
#include "base/rand_util.h"
#include "base/version.h" #include "base/version.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/updater/activity.h" #include "chrome/updater/activity.h"
...@@ -49,7 +51,7 @@ Configurator::Configurator(std::unique_ptr<UpdaterPrefs> prefs) ...@@ -49,7 +51,7 @@ Configurator::Configurator(std::unique_ptr<UpdaterPrefs> prefs)
Configurator::~Configurator() = default; Configurator::~Configurator() = default;
int Configurator::InitialDelay() const { int Configurator::InitialDelay() const {
return 0; return base::RandInt(0, external_constants_->InitialDelay());
} }
int Configurator::NextCheckDelay() const { int Configurator::NextCheckDelay() const {
......
...@@ -48,6 +48,7 @@ const char kUninstallScript[] = "uninstall.cmd"; ...@@ -48,6 +48,7 @@ const char kUninstallScript[] = "uninstall.cmd";
// Developer override key names. // Developer override key names.
const char kDevOverrideKeyUrl[] = "url"; const char kDevOverrideKeyUrl[] = "url";
const char kDevOverrideKeyUseCUP[] = "use_cup"; const char kDevOverrideKeyUseCUP[] = "use_cup";
const char kDevOverrideKeyInitialDelay[] = "initial_delay";
// Policy Management constants. // Policy Management constants.
const char kProxyModeDirect[] = "direct"; const char kProxyModeDirect[] = "direct";
......
...@@ -126,6 +126,7 @@ extern const char kUninstallScript[]; ...@@ -126,6 +126,7 @@ extern const char kUninstallScript[];
// Developer override keys. // Developer override keys.
extern const char kDevOverrideKeyUrl[]; extern const char kDevOverrideKeyUrl[];
extern const char kDevOverrideKeyUseCUP[]; extern const char kDevOverrideKeyUseCUP[];
extern const char kDevOverrideKeyInitialDelay[];
// Timing constants. // Timing constants.
#if defined(OS_WIN) #if defined(OS_WIN)
...@@ -205,11 +206,7 @@ constexpr int kUninstallPingReasonUserNotAnOwner = 1; ...@@ -205,11 +206,7 @@ constexpr int kUninstallPingReasonUserNotAnOwner = 1;
// The file downloaded to a temporary location could not be moved. // The file downloaded to a temporary location could not be moved.
constexpr int kErrorFailedToMoveDownloadedFile = 5; constexpr int kErrorFailedToMoveDownloadedFile = 5;
// TODO(crbug.com/1144151): This constant should be `60` for production code and constexpr int kInitialDelay = 60;
// `0.1` for test code. Due to test timeout limitation, the full jitter interval
// (0 to 60 seconds) cannot be tested. A jitter in the interval of 0 to 0.1
// seconds should be used for testing.
constexpr double kUpdateCheckJitterMultiplier = 0.1;
} // namespace updater } // namespace updater
......
...@@ -24,6 +24,8 @@ class DefaultExternalConstants : public ExternalConstants { ...@@ -24,6 +24,8 @@ class DefaultExternalConstants : public ExternalConstants {
} }
bool UseCUP() const override { return true; } bool UseCUP() const override { return true; }
int InitialDelay() const override { return kInitialDelay; }
}; };
} // namespace } // namespace
......
...@@ -27,6 +27,13 @@ class ExternalConstants { ...@@ -27,6 +27,13 @@ class ExternalConstants {
// True if client update protocol signing of update checks is enabled. // True if client update protocol signing of update checks is enabled.
virtual bool UseCUP() const = 0; virtual bool UseCUP() const = 0;
// Returns a random value in seconds used to delay the start of the automated
// background tasks such as update checks. This distributes the update server
// load more uniformly and avoids the problem of a large number of clients
// creating load spikes on servers when checking for updates and their system
// time is synchronized by a time server.
virtual int InitialDelay() const = 0;
protected: protected:
std::unique_ptr<ExternalConstants> next_provider_; std::unique_ptr<ExternalConstants> next_provider_;
}; };
......
...@@ -20,6 +20,7 @@ class DevOverrideProvider : public ExternalConstants { ...@@ -20,6 +20,7 @@ class DevOverrideProvider : public ExternalConstants {
// Overrides of ExternalConstants: // Overrides of ExternalConstants:
std::vector<GURL> UpdateURL() const override; std::vector<GURL> UpdateURL() const override;
bool UseCUP() const override; bool UseCUP() const override;
int InitialDelay() const override;
}; };
} // namespace updater } // namespace updater
......
...@@ -42,4 +42,18 @@ bool DevOverrideProvider::UseCUP() const { ...@@ -42,4 +42,18 @@ bool DevOverrideProvider::UseCUP() const {
} }
} }
int DevOverrideProvider::InitialDelay() const {
@autoreleasepool {
NSUserDefaults* userDefaults = [[NSUserDefaults alloc]
initWithSuiteName:[NSString
stringWithUTF8String:kUserDefaultsSuiteName]];
id initial_delay = [userDefaults
objectForKey:[NSString
stringWithUTF8String:kDevOverrideKeyInitialDelay]];
if (initial_delay)
return [initial_delay integerValue];
return next_provider_->InitialDelay();
}
}
} // namespace updater } // namespace updater
...@@ -27,6 +27,9 @@ void ClearUserDefaults() { ...@@ -27,6 +27,9 @@ void ClearUserDefaults() {
[userDefaults [userDefaults
removeObjectForKey:[NSString removeObjectForKey:[NSString
stringWithUTF8String:kDevOverrideKeyUseCUP]]; stringWithUTF8String:kDevOverrideKeyUseCUP]];
[userDefaults
removeObjectForKey:
[NSString stringWithUTF8String:kDevOverrideKeyInitialDelay]];
} }
} }
...@@ -52,6 +55,9 @@ TEST_F(DevOverrideTest, TestDevOverrides) { ...@@ -52,6 +55,9 @@ TEST_F(DevOverrideTest, TestDevOverrides) {
[userDefaults [userDefaults
setBool:NO setBool:NO
forKey:[NSString stringWithUTF8String:kDevOverrideKeyUseCUP]]; forKey:[NSString stringWithUTF8String:kDevOverrideKeyUseCUP]];
[userDefaults
setInteger:0
forKey:[NSString stringWithUTF8String:kDevOverrideKeyInitialDelay]];
} }
EXPECT_FALSE(consts->UseCUP()); EXPECT_FALSE(consts->UseCUP());
...@@ -59,6 +65,7 @@ TEST_F(DevOverrideTest, TestDevOverrides) { ...@@ -59,6 +65,7 @@ TEST_F(DevOverrideTest, TestDevOverrides) {
ASSERT_EQ(urls.size(), 1u); ASSERT_EQ(urls.size(), 1u);
EXPECT_EQ(urls[0], GURL("http://localhost:8080")); EXPECT_EQ(urls[0], GURL("http://localhost:8080"));
ASSERT_TRUE(urls[0].is_valid()); ASSERT_TRUE(urls[0].is_valid());
ASSERT_EQ(consts->InitialDelay(), 0);
} }
} // namespace updater } // namespace updater
...@@ -39,4 +39,15 @@ bool DevOverrideProvider::UseCUP() const { ...@@ -39,4 +39,15 @@ bool DevOverrideProvider::UseCUP() const {
return next_provider_->UseCUP(); return next_provider_->UseCUP();
} }
int DevOverrideProvider::InitialDelay() const {
base::win::RegKey key;
if (key.Open(HKEY_CURRENT_USER, UPDATE_DEV_KEY, KEY_READ) == ERROR_SUCCESS) {
DWORD initial_delay = 0;
if (key.ReadValueDW(base::UTF8ToUTF16(kDevOverrideKeyInitialDelay).c_str(),
&initial_delay) == ERROR_SUCCESS)
return initial_delay;
}
return next_provider_->InitialDelay();
}
} // namespace updater } // namespace updater
...@@ -46,12 +46,18 @@ TEST_F(DevOverrideTest, TestDevOverrides) { ...@@ -46,12 +46,18 @@ TEST_F(DevOverrideTest, TestDevOverrides) {
ASSERT_EQ( ASSERT_EQ(
key.WriteValue(base::UTF8ToUTF16(kDevOverrideKeyUseCUP).c_str(), use_cup), key.WriteValue(base::UTF8ToUTF16(kDevOverrideKeyUseCUP).c_str(), use_cup),
ERROR_SUCCESS); ERROR_SUCCESS);
DWORD initial_delay = 1;
ASSERT_EQ(
key.WriteValue(base::UTF8ToUTF16(kDevOverrideKeyInitialDelay).c_str(),
initial_delay),
ERROR_SUCCESS);
ASSERT_FALSE(consts->UseCUP()); ASSERT_FALSE(consts->UseCUP());
std::vector<GURL> urls = consts->UpdateURL(); std::vector<GURL> urls = consts->UpdateURL();
ASSERT_EQ(urls.size(), 1u); ASSERT_EQ(urls.size(), 1u);
ASSERT_EQ(urls[0], GURL("http://localhost:8080")); ASSERT_EQ(urls[0], GURL("http://localhost:8080"));
ASSERT_TRUE(urls[0].is_valid()); ASSERT_TRUE(urls[0].is_valid());
ASSERT_EQ(consts->InitialDelay(), 1);
} }
} // namespace updater } // namespace updater
...@@ -112,6 +112,9 @@ void EnterTestMode(const GURL& url) { ...@@ -112,6 +112,9 @@ void EnterTestMode(const GURL& url) {
[userDefaults [userDefaults
setBool:NO setBool:NO
forKey:[NSString stringWithUTF8String:kDevOverrideKeyUseCUP]]; forKey:[NSString stringWithUTF8String:kDevOverrideKeyUseCUP]];
[userDefaults
setInteger:0
forKey:[NSString stringWithUTF8String:kDevOverrideKeyInitialDelay]];
} }
} }
......
...@@ -109,6 +109,10 @@ void EnterTestMode(const GURL& url) { ...@@ -109,6 +109,10 @@ void EnterTestMode(const GURL& url) {
ASSERT_EQ(key.WriteValue(base::UTF8ToUTF16(kDevOverrideKeyUseCUP).c_str(), ASSERT_EQ(key.WriteValue(base::UTF8ToUTF16(kDevOverrideKeyUseCUP).c_str(),
DWORD{0}), DWORD{0}),
ERROR_SUCCESS); ERROR_SUCCESS);
ASSERT_EQ(
key.WriteValue(base::UTF8ToUTF16(kDevOverrideKeyInitialDelay).c_str(),
DWORD{0}),
ERROR_SUCCESS);
} }
void ExpectInstalled() { void ExpectInstalled() {
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/rand_util.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "base/task/thread_pool.h" #include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/sequenced_task_runner_handle.h"
...@@ -180,7 +179,7 @@ void CheckForUpdatesTask::MaybeCheckForUpdates() { ...@@ -180,7 +179,7 @@ void CheckForUpdatesTask::MaybeCheckForUpdates() {
base::BindOnce(&CheckForUpdatesTask::MaybeCheckForUpdatesDone, base::BindOnce(&CheckForUpdatesTask::MaybeCheckForUpdatesDone,
this), this),
config_)), config_)),
UpdateCheckJitter()); base::TimeDelta::FromSeconds(config_->InitialDelay()));
} }
void CheckForUpdatesTask::MaybeCheckForUpdatesDone() { void CheckForUpdatesTask::MaybeCheckForUpdatesDone() {
...@@ -271,11 +270,6 @@ void CheckForUpdatesTask::UninstallPingSent(update_client::Error error) { ...@@ -271,11 +270,6 @@ void CheckForUpdatesTask::UninstallPingSent(update_client::Error error) {
} // namespace } // namespace
base::TimeDelta UpdateCheckJitter() {
return base::TimeDelta::FromSecondsD(base::RandDouble() *
kUpdateCheckJitterMultiplier);
}
UpdateServiceInternalImpl::UpdateServiceInternalImpl( UpdateServiceInternalImpl::UpdateServiceInternalImpl(
scoped_refptr<updater::Configurator> config) scoped_refptr<updater::Configurator> config)
: config_(config) {} : config_(config) {}
......
...@@ -19,13 +19,6 @@ ...@@ -19,13 +19,6 @@
namespace updater { namespace updater {
// Returns a random `TimeDelta` value used to delay the start of the automated
// background tasks such as update checks. This distributes the update server
// load more uniformly and avoids the problem of a large number of clients
// creating load spikes on servers when checking for updates and their system
// time is synchronized by a time server.
base::TimeDelta UpdateCheckJitter();
class Configurator; class Configurator;
// All functions and callbacks must be called on the same sequence. // All functions and callbacks must be called on the same sequence.
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/updater/update_service_internal_impl.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace updater {
TEST(UpdateServiceInternalImplTest, UpdateCheckJitter) {
for (int i = 0; i < 100; ++i) {
base::TimeDelta jitter = UpdateCheckJitter();
EXPECT_GE(jitter, base::TimeDelta::FromSeconds(0));
EXPECT_LT(jitter, base::TimeDelta::FromSeconds(60));
}
}
} // namespace updater
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment