| // Copyright 2012 Google Inc. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // |
| // An abstraction for scheduling recurring tasks. Combines idempotent scheduling |
| // and smearing with conditional retries and exponential backoff. Does not |
| // implement throttling. Designed to support a variety of use cases, including |
| // the following capabilities. |
| // |
| // * Idempotent scheduling, e.g., ensuring that a batching task is scheduled |
| // exactly once. |
| // * Recurring tasks, e.g., periodic heartbeats. |
| // * Retriable actions aimed at state change, e.g., sending initialization |
| // messages. |
| // |
| // Each instance of this class manages the state for a single task. See the |
| // invalidation-client-impl.cc for examples. |
| |
| #ifndef GOOGLE_CACHEINVALIDATION_IMPL_RECURRING_TASK_H_ |
| #define GOOGLE_CACHEINVALIDATION_IMPL_RECURRING_TASK_H_ |
| |
| #include "google/cacheinvalidation/include/system-resources.h" |
| #include "google/cacheinvalidation/impl/exponential-backoff-delay-generator.h" |
| #include "google/cacheinvalidation/impl/smearer.h" |
| |
| namespace invalidation { |
| |
| class RecurringTask { |
| public: |
| /* Creates a recurring task with the given parameters. The specs of the |
| * parameters are given in the instance variables. |
| * |
| * The created task is first scheduled with a smeared delay of |
| * |initial_delay|. If the |this->run()| returns true on its execution, the |
| * task is rescheduled after a |timeout_delay| + smeared delay of |
| * |initial_delay| or |timeout_delay| + |delay_generator->GetNextDelay()| |
| * depending on whether the |delay_generator| is null or not. |
| * |
| * Space for |scheduler|, |logger|, |smearer| is owned by the caller. |
| * Space for |delay_generator| is owned by the callee. |
| */ |
| RecurringTask(string name, Scheduler* scheduler, Logger* logger, |
| Smearer* smearer, ExponentialBackoffDelayGenerator* delay_generator, |
| TimeDelta initial_delay, TimeDelta timeout_delay); |
| |
| virtual ~RecurringTask() {} |
| |
| /* Run the task and return true if the task should be rescheduled after a |
| * timeout. If false is returned, the task is not scheduled again until |
| * |ensure_scheduled| is called again. |
| */ |
| virtual bool RunTask() = 0; |
| |
| /* Ensures that the task is scheduled (with |debug_reason| as the reason to be |
| * printed for debugging purposes). If the task has been scheduled, it is |
| * not scheduled again. |
| * |
| * REQUIRES: Must be called from the scheduler thread. |
| */ |
| void EnsureScheduled(string debug_reason); |
| |
| /* Space for the returned Smearer is still owned by this class. */ |
| Smearer* smearer() { |
| return smearer_; |
| } |
| |
| private: |
| /* Run the task and check if it needs to be rescheduled. If so, reschedule it |
| * after the appropriate delay. |
| */ |
| void RunTaskAndRescheduleIfNeeded(); |
| |
| /* Ensures that the task is scheduled if it is already not scheduled. If |
| * already scheduled, this method is a no-op. If |is_retry| is |false|, smears |
| * the |initial_delay_| and uses that delay for scheduling. If |is_retry| is |
| * true, it determines the new delay to be |
| * |timeout_delay_ + delay_generator.GetNextDelay()| if |delay_generator| is |
| * non-null. If |delay_generator| is null, schedules the task after a delay of |
| * |timeout_delay_| + smeared value of |initial_delay_|. |
| * |
| * REQUIRES: Must be called from the scheduler thread. |
| */ |
| void EnsureScheduled(bool is_retry, string debug_reason); |
| |
| /* Name of the task (for debugging purposes mostly). */ |
| string name_; |
| |
| /* Scheduler for the scheduling the task as needed. */ |
| Scheduler* scheduler_; |
| |
| /* A logger. */ |
| Logger* logger_; |
| |
| /* A smearer for spreading the delays. */ |
| Smearer* smearer_; |
| |
| /* A delay generator for exponential backoff. */ |
| scoped_ptr<ExponentialBackoffDelayGenerator> delay_generator_; |
| |
| /* |
| * The time after which the task is scheduled first. If no delayGenerator is |
| * specified, this is also the delay used for retries. |
| */ |
| TimeDelta initial_delay_; |
| |
| /* For a task that is retried, add this time to the delay. */ |
| TimeDelta timeout_delay_; |
| |
| /* If the task has been currently scheduled. */ |
| bool is_scheduled_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RecurringTask); |
| }; |
| |
| } // namespace invalidation |
| |
| #endif // GOOGLE_CACHEINVALIDATION_IMPL_RECURRING_TASK_H_ |