| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_ |
| #define COMPONENTS_SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| |
| #include "base/cancelable_callback.h" |
| #include "base/compiler_specific.h" |
| #include "base/functional/callback.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/sequence_checker.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #include "base/timer/wall_clock_timer.h" |
| #include "base/types/strong_alias.h" |
| #include "components/sync/engine/cycle/nudge_tracker.h" |
| #include "components/sync/engine/cycle/sync_cycle.h" |
| #include "components/sync/engine/cycle/sync_cycle_context.h" |
| #include "components/sync/engine/net/server_connection_manager.h" |
| #include "components/sync/engine/polling_constants.h" |
| #include "components/sync/engine/sync_scheduler.h" |
| #include "components/sync/engine/syncer.h" |
| |
| namespace syncer { |
| |
| class BackoffDelayProvider; |
| struct ModelNeutralState; |
| |
| // Lives on the sync sequence. |
| class SyncSchedulerImpl : public SyncScheduler { |
| public: |
| // `name` is a display string to identify the sync sequence. |
| SyncSchedulerImpl(const std::string& name, |
| std::unique_ptr<BackoffDelayProvider> delay_provider, |
| SyncCycleContext* context, |
| std::unique_ptr<Syncer> syncer, |
| bool ignore_auth_credentials); |
| |
| SyncSchedulerImpl(const SyncSchedulerImpl&) = delete; |
| SyncSchedulerImpl& operator=(const SyncSchedulerImpl&) = delete; |
| |
| // Calls Stop(). |
| ~SyncSchedulerImpl() override; |
| |
| void Start(Mode mode, base::Time last_poll_time) override; |
| void ScheduleConfiguration(sync_pb::SyncEnums::GetUpdatesOrigin origin, |
| DataTypeSet types_to_download, |
| base::OnceClosure ready_task) override; |
| void Stop() override; |
| void ScheduleLocalNudge(DataType type) override; |
| void ScheduleLocalRefreshRequest(DataTypeSet types) override; |
| void ScheduleInvalidationNudge(DataType type) override; |
| void ScheduleInitialSyncNudge(DataType data_type) override; |
| void SetNotificationsEnabled(bool notifications_enabled) override; |
| void SetHasPendingInvalidations(DataType type, |
| bool has_invalidations) override; |
| |
| void OnCredentialsUpdated() override; |
| void OnConnectionStatusChange(network::mojom::ConnectionType type) override; |
| |
| // SyncCycle::Delegate implementation. |
| void OnThrottled(const base::TimeDelta& throttle_duration) override; |
| void OnTypesThrottled(DataTypeSet types, |
| const base::TimeDelta& throttle_duration) override; |
| void OnTypesBackedOff(DataTypeSet types) override; |
| bool IsAnyThrottleOrBackoff() override; |
| void OnReceivedPollIntervalUpdate( |
| const base::TimeDelta& new_interval) override; |
| void OnReceivedCustomNudgeDelays( |
| const std::map<DataType, base::TimeDelta>& nudge_delays) override; |
| void OnSyncProtocolError( |
| const SyncProtocolError& sync_protocol_error) override; |
| void OnReceivedMigrationRequest(DataTypeSet types) override; |
| void OnReceivedQuotaParamsForExtensionTypes( |
| std::optional<int> max_tokens, |
| std::optional<base::TimeDelta> refill_interval, |
| std::optional<base::TimeDelta> depleted_quota_nudge_delay) override; |
| |
| bool IsGlobalThrottle() const; |
| bool IsGlobalBackoff() const; |
| |
| // Reduces nudge delays for all types to a very short value and prevents their |
| // further changing by the server. Used to speed up passing of integration |
| // tests. |
| void ForceShortNudgeDelayForTest(); |
| |
| private: |
| struct ConfigurationParams { |
| ConfigurationParams(sync_pb::SyncEnums::GetUpdatesOrigin origin, |
| DataTypeSet types_to_download, |
| base::OnceClosure ready_task); |
| ~ConfigurationParams(); |
| |
| ConfigurationParams(const ConfigurationParams&) = delete; |
| ConfigurationParams& operator=(const ConfigurationParams&) = delete; |
| |
| const sync_pb::SyncEnums::GetUpdatesOrigin origin; |
| const DataTypeSet types_to_download; |
| // Callback to invoke on configuration completion. |
| base::OnceClosure ready_task; |
| }; |
| |
| // Used as a parameter when triggering sync cycle jobs. Determines whether to |
| // respect or ignore any global backoff. (In the usual case where the client |
| // is NOT backed off, this makes no difference. It also doesn't affect |
| // per-data-type backoff.) |
| using RespectGlobalBackoff = |
| base::StrongAlias<class RespectGlobalBackoffTag, bool>; |
| |
| enum PollAdjustType { |
| // Restart the poll interval. |
| FORCE_RESET, |
| // Restart the poll interval only if its length has changed. |
| UPDATE_INTERVAL, |
| }; |
| |
| friend class SyncSchedulerImplTest; |
| |
| static const char* GetModeString(Mode mode); |
| |
| // Invoke the syncer to perform a nudge job. |
| void DoNudgeSyncCycleJob(); |
| |
| // Invoke the syncer to perform a configuration job. |
| void DoConfigurationSyncCycleJob(RespectGlobalBackoff respect_backoff); |
| |
| // Helper function for Do{Nudge,Configuration,Poll}SyncCycleJob. |
| void HandleSuccess(); |
| |
| // Helper function for Do{Nudge,Configuration,Poll}SyncCycleJob. |
| void HandleFailure(const ModelNeutralState& model_neutral_state); |
| |
| // Invoke the Syncer to perform a poll job. |
| void DoPollSyncCycleJob(); |
| |
| // Helper function to calculate poll interval. |
| base::TimeDelta GetPollInterval(); |
| |
| // Adjusts the poll timer to account for new poll interval, and possibly |
| // resets the poll interval, depedning on the flag's value. |
| void AdjustPolling(PollAdjustType type); |
| |
| // Helper to restart pending_wakeup_timer_. |
| // This function need to be called in 3 conditions, backoff/throttling |
| // happens, unbackoff/unthrottling happens and after `PerformDelayedNudge` |
| // runs. |
| // This function is for scheduling unbackoff/unthrottling jobs, and the |
| // poriority is, global unbackoff/unthrottling job first, if there is no |
| // global backoff/throttling, then try to schedule types |
| // unbackoff/unthrottling job. |
| void RestartWaiting(); |
| |
| // Determines if we're allowed to contact the server right now. |
| bool CanRunJobNow(RespectGlobalBackoff respect_backoff); |
| |
| // Determines if we're allowed to contact the server right now. |
| bool CanRunNudgeJobNow(RespectGlobalBackoff respect_backoff); |
| |
| // If the scheduler's current state supports it, this will create a job based |
| // on the passed in parameters and coalesce it with any other pending jobs, |
| // then post a delayed task to run it. It may also choose to drop the job or |
| // save it for later, depending on the scheduler's current state. |
| void ScheduleNudgeImpl(const base::TimeDelta& delay); |
| |
| // Helper to signal listeners about changed retry time. |
| void NotifyRetryTime(base::Time retry_time); |
| |
| // Helper to signal listeners about changed throttled or backed off types. |
| void NotifyBlockedTypesChanged(); |
| |
| // Looks for pending work and, if it finds any, runs it. TrySyncCycleJob just |
| // posts a call to TrySyncCycleJobImpl on the current sequence. |
| void TrySyncCycleJob(RespectGlobalBackoff respect_backoff); |
| void TrySyncCycleJobImpl(RespectGlobalBackoff respect_backoff); |
| |
| // Transitions out of the THROTTLED WaitInterval then triggers a job which |
| // ignores global backoff. This is used for global throttling. |
| void Unthrottle(); |
| |
| // Called when a per-type throttling or backing off interval expires. |
| void OnTypesUnblocked(); |
| |
| // Runs a normal nudge job when the scheduled timer expires. |
| void PerformDelayedNudge(); |
| |
| // Attempts to exit global backoff (BlockingMode::kExponentialBackoff) by |
| // triggering a job which ignores global backoff. |
| void ExponentialBackoffRetry(); |
| |
| // Called when the root cause of the current connection error is fixed. |
| void OnServerConnectionErrorFixed(); |
| |
| // Creates a cycle for a poll and performs the sync. |
| void PollTimerCallback(); |
| |
| // Returns the set of types that are enabled and not currently throttled and |
| // backed off. |
| DataTypeSet GetEnabledAndUnblockedTypes(); |
| |
| // Called as we are started to broadcast an initial cycle snapshot |
| // containing data like initial_sync_ended. Important when the client starts |
| // up and does not need to perform an initial sync. |
| void SendInitialSnapshot(); |
| |
| bool IsEarlierThanCurrentPendingJob(const base::TimeDelta& delay); |
| |
| // Used for logging. |
| const std::string name_; |
| |
| // Set in Start(), unset in Stop(). |
| bool started_ = false; |
| |
| // The interval between poll requests. Can be updated by the server. |
| base::TimeDelta syncer_poll_interval_; |
| |
| // Timer for polling. Restarted on each successful poll, and when entering |
| // normal sync mode or exiting an error state. Not active in configuration |
| // mode. |
| // Note that this is a WallClockTimer (as opposed to a regular OneShotTimer) |
| // so that it continues counting even if the device is suspended. |
| base::WallClockTimer poll_timer_; |
| |
| // The mode of operation. |
| Mode mode_ = CONFIGURATION_MODE; |
| |
| // Current wait state. Null if we're not in backoff and not throttled. |
| std::unique_ptr<WaitInterval> wait_interval_; |
| |
| std::unique_ptr<BackoffDelayProvider> delay_provider_; |
| |
| // The timer for the next pending task (except for polling, which has its own |
| // timer). This can be a delayed nudge (standard case), or throttling/backoff |
| // (either global or for some data type(s)). |
| // TODO(crbug.com/40939309): Maybe use a WallClockTimer, so that |
| // throttling/backoff continue counting even if the device is suspended? |
| base::OneShotTimer pending_wakeup_timer_; |
| |
| // Storage for variables related to an in-progress configure request. Note |
| // that (mode_ != CONFIGURATION_MODE) \implies !pending_configure_params_. |
| std::unique_ptr<ConfigurationParams> pending_configure_params_; |
| |
| // Keeps track of work that the syncer needs to handle. |
| NudgeTracker nudge_tracker_; |
| |
| // Invoked to run through the sync cycle. |
| const std::unique_ptr<Syncer> syncer_; |
| |
| const raw_ptr<SyncCycleContext> cycle_context_; |
| |
| // The time when the last poll request finished. Used for computing the next |
| // poll time. |
| base::Time last_poll_reset_time_; |
| |
| // Dictates if the scheduler should wait for authentication to happen or not. |
| const bool ignore_auth_credentials_; |
| |
| // Used to prevent changing nudge delays by the server in integration tests. |
| bool force_short_nudge_delay_for_test_ = false; |
| |
| SEQUENCE_CHECKER(sequence_checker_); |
| |
| base::WeakPtrFactory<SyncSchedulerImpl> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace syncer |
| |
| #endif // COMPONENTS_SYNC_ENGINE_SYNC_SCHEDULER_IMPL_H_ |