From 7831fff2335f44f33049c2461aee53ca4f7d0bab Mon Sep 17 00:00:00 2001 From: Jacob Dahl <37091262+dakejahl@users.noreply.github.com> Date: Mon, 27 Jul 2026 15:39:49 -0600 Subject: [PATCH] fix(upload): stop spamming when flight-review is offline When the local flight-review server is down, the upload loop previously probed and logged a failure for every pending log. Probe once, log a single unreachable message with a 60s cooldown, and bail the current upload batch (HTTP 503) instead of walking the queue. (cherry picked from commit 7a23c8e894c8f73fb1ac319a78c41963fd99eadf) --- src/LogLoader.cpp | 5 +++++ src/ServerInterface.cpp | 38 ++++++++++++++++++++++++++++++++++---- src/ServerInterface.hpp | 12 +++++++++++- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/LogLoader.cpp b/src/LogLoader.cpp index 62a4782..70f8f6e 100644 --- a/src/LogLoader.cpp +++ b/src/LogLoader.cpp @@ -408,6 +408,11 @@ void LogLoader::upload_pending_logs(std::shared_ptr server) } else if (result.status_code == 400) { LOG("Log upload failed (" << result.status_code << "): " << result.message); + } else if (result.status_code == 503) { + // Server down (e.g. local flight-review not running). Already logged once + // with a cooldown in ServerInterface; do not walk the rest of the queue. + return; + } else { LOG("Log upload TEMPORARILY FAILED (" << result.status_code << "): " << result.message << " - Will retry later"); diff --git a/src/ServerInterface.cpp b/src/ServerInterface.cpp index 6e78ac4..bd1e6c3 100644 --- a/src/ServerInterface.cpp +++ b/src/ServerInterface.cpp @@ -418,7 +418,9 @@ ServerInterface::UploadResult ServerInterface::upload(const std::string& filepat } if (!server_reachable()) { - return {false, 0, "Server unreachable: " + _settings.server_url}; + // 503: treat as service unavailable so the upload loop can bail the batch + // instead of hammering a dead local flight-review for every pending log. + return {false, 503, "Server unreachable: " + _settings.server_url}; } std::ifstream file(filepath, std::ios::binary); @@ -470,24 +472,52 @@ ServerInterface::UploadResult ServerInterface::upload(const std::string& filepat bool ServerInterface::server_reachable() { + const auto now = std::chrono::steady_clock::now(); + + // Still inside the cooldown from a previous failure — do not re-probe or re-log. + if (now < _unreachable_until) { + return false; + } + httplib::Result res; if (_protocol == Protocol::Https) { httplib::SSLClient cli(_settings.server_url); + cli.set_connection_timeout(2, 0); + cli.set_read_timeout(2, 0); res = cli.Get("/"); } else { httplib::Client cli(_settings.server_url); + cli.set_connection_timeout(2, 0); + cli.set_read_timeout(2, 0); res = cli.Get("/"); } - bool success = res && res->status == 200; + const bool success = res && res->status == 200; if (!success) { - LOG("Connection to " << _settings.server_url << " failed: " << (res ? std::to_string(res->status) : "No response")); + _unreachable_until = now + kUnreachableCooldown; + + if (!_reported_unreachable) { + const std::string detail = res ? ("HTTP " + std::to_string(res->status)) : "No response"; + LOG("Upload server " << _settings.server_url << " unreachable (" << detail + << "); skipping uploads for " + << std::chrono::duration_cast(kUnreachableCooldown).count() + << "s"); + _reported_unreachable = true; + } + + return false; } - return success; + if (_reported_unreachable) { + LOG("Upload server " << _settings.server_url << " is reachable again"); + _reported_unreachable = false; + } + + _unreachable_until = {}; + return true; } bool ServerInterface::init_database() diff --git a/src/ServerInterface.hpp b/src/ServerInterface.hpp index ad0f156..3d8e014 100644 --- a/src/ServerInterface.hpp +++ b/src/ServerInterface.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -19,7 +20,9 @@ class ServerInterface struct UploadResult { bool success; - int status_code; // HTTP status code, or 0 if not applicable + // HTTP status, or 0 when not applicable. 503 means the server is unreachable + // (connectivity); callers should stop the current upload batch and retry later. + int status_code; std::string message; }; @@ -100,4 +103,11 @@ class ServerInterface bool _should_exit = false; bool _has_legacy_table = false; sqlite3* _db = nullptr; + + // When flight-review (or any upload target) is down, avoid probing and logging + // once per pending log. Probe at most every kUnreachableCooldown, and log only on + // the down/up transitions. + static constexpr auto kUnreachableCooldown = std::chrono::seconds(60); + std::chrono::steady_clock::time_point _unreachable_until {}; + bool _reported_unreachable {false}; };