diff --git a/src/backoff.h b/src/backoff.h new file mode 100644 index 0000000..ad14143 --- /dev/null +++ b/src/backoff.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include + +struct Backoff +{ + int64_t minAmount; + int64_t maxAmount; + int64_t current; + int fails; + std::mt19937_64 randGenerator; + std::uniform_real_distribution<> randDistribution; + + double rand01() { + return randDistribution(randGenerator); + } + + Backoff(int64_t min, int64_t max) + : minAmount(min) + , maxAmount(max) + , current(min) + , fails(0) + {} + + void reset() + { + fails = 0; + current = minAmount; + } + + int64_t nextDelay() + { + ++fails; + int64_t delay = (int64_t)((double)current * 2.0 * rand01()); + current = std::min(current + delay, maxAmount); + return current; + } +}; + diff --git a/src/discord-rpc.cpp b/src/discord-rpc.cpp index a766c2f..0240580 100644 --- a/src/discord-rpc.cpp +++ b/src/discord-rpc.cpp @@ -2,13 +2,18 @@ #include "rpc_connection.h" #include "yolojson.h" +#include "backoff.h" + #include "rapidjson/document.h" #include #include #include + +#ifndef DISCORD_DISABLE_IO_THREAD #include #include +#endif constexpr size_t MaxMessageSize = 16 * 1024; constexpr size_t MessageQueueSize = 8; @@ -29,6 +34,8 @@ static QueuedMessage SendQueue[MessageQueueSize]{}; static std::atomic_uint SendQueueNextAdd{0}; static std::atomic_uint SendQueueNextSend{0}; static std::atomic_uint SendQueuePendingSends{0}; +static Backoff ReconnectTimeMs(500, 60 * 1000); +static auto NextConnect{std::chrono::system_clock::now()}; #ifndef DISCORD_DISABLE_IO_THREAD static std::atomic_bool KeepRunning{ true }; @@ -37,6 +44,11 @@ static std::condition_variable WaitForIOActivity; static std::thread IoThread; #endif // DISCORD_DISABLE_IO_THREAD +static void UpdateReconnectTime() +{ + NextConnect = std::chrono::system_clock::now() + std::chrono::duration{ReconnectTimeMs.nextDelay()}; +} + static QueuedMessage* SendQueueGetNextAddMessage() { // if we are falling behind, bail if (SendQueuePendingSends.load() >= MessageQueueSize) { @@ -56,7 +68,10 @@ static void SendQueueCommitMessage() { extern "C" void Discord_UpdateConnection() { if (!Connection->IsOpen()) { - Connection->Open(); + if (std::chrono::system_clock::now() >= NextConnect) { + UpdateReconnectTime(); + Connection->Open(); + } } else { // reads @@ -108,11 +123,13 @@ extern "C" void Discord_Initialize(const char* applicationId, DiscordEventHandle Connection = RpcConnection::Create(applicationId); Connection->onConnect = []() { WasJustConnected.exchange(true); + ReconnectTimeMs.reset(); }; Connection->onDisconnect = [](int err, const char* message) { LastErrorCode = err; StringCopy(LastErrorMessage, message, sizeof(LastErrorMessage)); WasJustDisconnected.exchange(true); + UpdateReconnectTime(); }; #ifndef DISCORD_DISABLE_IO_THREAD