ORE Studio 0.0.4
Loading...
Searching...
No Matches
retry_strategy.hpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 *
3 * Copyright (C) 2026 Marco Craveiro <marco.craveiro@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 3 of the License, or (at your option) any later
8 * version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
16 * Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19#ifndef ORES_UTILITY_CONCURRENCY_RETRY_STRATEGY_HPP
20#define ORES_UTILITY_CONCURRENCY_RETRY_STRATEGY_HPP
21
22#include <algorithm>
23#include <chrono>
24
25namespace ores::utility::concurrency {
26
45public:
46 struct config {
47 std::chrono::seconds initial_delay{5};
48 std::chrono::seconds max_delay{300};
49 std::chrono::seconds reset_threshold{60};
50 };
51
52 retry_strategy() = default;
53 explicit retry_strategy(config cfg) : config_(cfg) {}
54
61 void on_start() {
62 last_start_ = std::chrono::steady_clock::now();
63 }
64
74 std::chrono::seconds on_failure() {
75 const auto uptime = std::chrono::steady_clock::now() - last_start_;
76 if (uptime >= config_.reset_threshold)
77 count_ = 0;
78
79 const auto delay = compute_delay();
80 ++count_;
81 return delay;
82 }
83
90 bool exceeded(int max) const { return count_ >= max; }
91
93 int failure_count() const { return count_; }
94
101 void set_failure_count(int n) { count_ = n; }
102
104 void reset() {
105 count_ = 0;
106 last_start_ = {};
107 }
108
109private:
110 std::chrono::seconds compute_delay() const {
111 // Cap exponent at 6: initial(5) * 2^6 = 320s > max(300s), so the
112 // min() clamp always applies from failure 6 onwards.
113 const int exp = std::min(count_, 6);
114 const auto delay = std::chrono::seconds(
115 config_.initial_delay.count() * (1 << exp));
116 return std::min(delay, config_.max_delay);
117 }
118
119 config config_{};
120 int count_ = 0;
121 std::chrono::steady_clock::time_point last_start_{};
122};
123
124} // namespace ores::utility::concurrency
125
126#endif
Stateful exponential-backoff retry calculator.
Definition retry_strategy.hpp:44
void on_start()
Record a successful start.
Definition retry_strategy.hpp:61
int failure_count() const
Returns the current consecutive failure count.
Definition retry_strategy.hpp:93
bool exceeded(int max) const
Returns whether the failure count has reached or exceeded max.
Definition retry_strategy.hpp:90
void set_failure_count(int n)
Restore a previously saved failure count without resetting state.
Definition retry_strategy.hpp:101
void reset()
Reset the counter and start-time record to initial state.
Definition retry_strategy.hpp:104
std::chrono::seconds on_failure()
Record a failure and compute the next backoff delay.
Definition retry_strategy.hpp:74