FastMM documentation
FastMM C++ API 0.6.0
Public headers, tier 1 and tier 2
Loading...
Searching...
No Matches
backoff.hpp
Go to the documentation of this file.
1#pragma once
2// Exponential backoff with jitter for reconnects: delay_n = cap_n * (1 - jitter) +
3// U(0, cap_n * jitter) where cap_n = min(max_ms, base_ms * 2^n). jitter = 1.0 is the
4// "full jitter" scheme (recommended: spreads a thundering herd of reconnects after a venue
5// outage), jitter = 0 is deterministic (useful in tests).
6#include <algorithm>
7#include <cmath>
8#include <cstdint>
9#include <random>
10
11namespace fastmm::net {
12
13struct BackoffConfig {
14 std::uint32_t base_ms = 250;
15 std::uint32_t max_ms = 30'000;
16 double jitter = 1.0; // fraction of the capped delay that is randomised, in [0, 1]
17};
20 public:
21 explicit ExponentialBackoff(BackoffConfig cfg = {}, std::uint64_t seed = 0x5eed) noexcept
22 : cfg_(cfg), rng_(seed) {
23 cfg_.jitter = std::clamp(cfg_.jitter, 0.0, 1.0);
24 if (cfg_.max_ms < cfg_.base_ms) cfg_.max_ms = cfg_.base_ms;
25 }
26
27 // Delay for the current attempt in milliseconds; advances the attempt counter.
28 std::uint32_t next_ms() noexcept {
29 const std::uint32_t cap = capped_delay(attempt_);
30 if (attempt_ < 31) ++attempt_;
31 const double fixed = static_cast<double>(cap) * (1.0 - cfg_.jitter);
32 const double random_span = static_cast<double>(cap) * cfg_.jitter;
33 std::uniform_real_distribution<double> dist(0.0, 1.0);
34 const double delay = fixed + random_span * dist(rng_);
35 return static_cast<std::uint32_t>(std::llround(delay));
36 }
37
38 void reset() noexcept { attempt_ = 0; }
39 std::uint32_t attempt() const noexcept { return attempt_; }
40 const BackoffConfig& config() const noexcept { return cfg_; }
42 // Upper bound of the delay for attempt n (before jitter) - exposed for tests/metrics.
43 std::uint32_t capped_delay(std::uint32_t attempt) const noexcept {
44 const std::uint64_t raw = static_cast<std::uint64_t>(cfg_.base_ms)
45 << std::min<std::uint32_t>(attempt, 31);
46 return static_cast<std::uint32_t>(std::min<std::uint64_t>(raw, cfg_.max_ms));
47 }
48
49 private:
50 BackoffConfig cfg_;
51 std::mt19937_64 rng_;
52 std::uint32_t attempt_ = 0;
53};
54
55} // namespace fastmm::net
Definition backoff.hpp:21
std::uint32_t attempt() const noexcept
Definition backoff.hpp:41
std::uint32_t next_ms() noexcept
Delay for the current attempt in milliseconds; advances the attempt counter.
Definition backoff.hpp:30
std::uint32_t capped_delay(std::uint32_t attempt) const noexcept
Upper bound of the delay for attempt n (before jitter) - exposed for tests/metrics.
Definition backoff.hpp:45
const BackoffConfig & config() const noexcept
Definition backoff.hpp:42
void reset() noexcept
Definition backoff.hpp:40
Definition reactor.hpp:37
Definition backoff.hpp:15
double jitter
fraction of the capped delay that is randomised, in [0, 1]
Definition backoff.hpp:18
std::uint32_t base_ms
Definition backoff.hpp:16
std::uint32_t max_ms
Definition backoff.hpp:17