diff --git a/core/include/userver/utils/periodic_task.hpp b/core/include/userver/utils/periodic_task.hpp index 22ba3147ae93..04ad2959f43c 100644 --- a/core/include/userver/utils/periodic_task.hpp +++ b/core/include/userver/utils/periodic_task.hpp @@ -67,17 +67,19 @@ class PeriodicTask final { constexpr /*implicit*/ Settings( std::chrono::milliseconds period, utils::Flags flags = {}, - logging::Level span_level = logging::Level::kInfo + logging::Level span_level = logging::Level::kInfo, + bool enabled = true ) - : Settings(period, kDistributionPercent, flags, span_level) {} + : Settings(period, kDistributionPercent, flags, span_level, enabled) {} constexpr Settings( std::chrono::milliseconds period, std::chrono::milliseconds distribution, utils::Flags flags = {}, - logging::Level span_level = logging::Level::kInfo + logging::Level span_level = logging::Level::kInfo, + bool enabled = true ) - : period(period), distribution(distribution), flags(flags), span_level(span_level) { + : period(period), distribution(distribution), flags(flags), span_level(span_level), enabled(enabled) { UASSERT(distribution <= period); } @@ -85,9 +87,10 @@ class PeriodicTask final { std::chrono::milliseconds period, uint8_t distribution_percent, utils::Flags flags = {}, - logging::Level span_level = logging::Level::kInfo + logging::Level span_level = logging::Level::kInfo, + bool enabled = true ) - : Settings(period, period * distribution_percent / 100, flags, span_level) { + : Settings(period, period * distribution_percent / 100, flags, span_level, enabled) { UASSERT(distribution_percent <= 100); } @@ -124,6 +127,9 @@ class PeriodicTask final { /// PeriodicTask::Start() calls engine::current_task::GetTaskProcessor() /// to get the TaskProcessor. engine::TaskProcessor* task_processor{nullptr}; + + /// @brief If false, the task will skip executions until re-enabled. + bool enabled{true}; }; /// Signature of the task to be executed each period. diff --git a/core/src/utils/periodic_task.cpp b/core/src/utils/periodic_task.cpp index da947d48e3f8..b2455bad5d59 100644 --- a/core/src/utils/periodic_task.cpp +++ b/core/src/utils/periodic_task.cpp @@ -22,8 +22,8 @@ namespace { auto TieSettings(const PeriodicTask::Settings& settings) { // Can't use Boost.Pfr, because Settings has custom constructors. - const auto& [f1, f2, f3, f4, f5, f6] = settings; - return std::tie(f1, f2, f3, f4, f5, f6); + const auto& [f1, f2, f3, f4, f5, f6, f7] = settings; + return std::tie(f1, f2, f3, f4, f5, f6, f7); } } // namespace @@ -106,7 +106,7 @@ void PeriodicTask::SetSettings(Settings settings) { return; } settings.flags = writer->flags; - should_notify_task = settings.period != writer->period || settings.exception_period != writer->exception_period; + should_notify_task = settings.period != writer->period || settings.exception_period != writer->exception_period || settings.enabled != writer->enabled; *writer = std::move(settings); writer.Commit(); } @@ -144,12 +144,13 @@ void PeriodicTask::Run() { while (!engine::current_task::ShouldCancel()) { const auto before = std::chrono::steady_clock::now(); bool no_exception = true; + bool force_step = should_force_step_.exchange(false); + const auto settings = settings_.Read(); - if (!std::exchange(skip_step, false)) { + if (force_step || (settings->enabled && !std::exchange(skip_step, false))) { no_exception = Step(); } - const auto settings = settings_.Read(); auto period = settings->period; const auto exception_period = settings->exception_period.value_or(period);