节点在线、应用在线、配置在线使用令牌查询
大石头 authored at 2021-12-16 19:49:30
1.37 KiB
Stardust
// SPDX-License-Identifier: MIT
#pragma once

#include <algorithm>
#include <atomic>
#include <chrono>
#include <cstdint>
#include <random>
#include <thread>

namespace staragent {

// Exponential backoff with jitter: 1s, 2s, 4s, 8s, 16s, 30s cap.
class Backoff
{
public:
    Backoff() : random_(std::random_device{}()) {}

    int NextDelayMs()
    {
        std::int64_t delay = 1000;
        for (int i = 0; i < attempt_ && delay < 30000; i++) delay *= 2;
        if (delay > 30000) delay = 30000;
        attempt_++;

        const double factor = 1.0 + (uniform_(random_) * 2.0 - 1.0) * 0.2;
        delay = static_cast<std::int64_t>(static_cast<double>(delay) * factor);
        if (delay < 1000) delay = 1000;
        if (delay > 30000) delay = 30000;
        return static_cast<int>(delay);
    }

    void Reset() { attempt_ = 0; }

    bool Wait(const std::atomic<bool>& stopping)
    {
        const int delay = NextDelayMs();
        const auto deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(delay);
        while (!stopping.load() && std::chrono::steady_clock::now() < deadline)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(50));
        }
        return !stopping.load();
    }

private:
    int attempt_ = 0;
    std::mt19937 random_;
    std::uniform_real_distribution<double> uniform_{0.0, 1.0};
};

} // namespace staragent