Loading src/backends/cluster.cpp +29 −9 Original line number Diff line number Diff line Loading @@ -326,20 +326,39 @@ namespace authdb { return; } } else { // No pending fetch — launch async retrieve (fire-and-forget). // Use cached data for this request; result is picked up on next call. // No pending fetch — launch async retrieve. // If the cache is empty (first fetch after startup), wait synchronously // with a timeout so the server doesn't show "waiting for peers" on every // first request. Subsequent fetches are fire-and-forget. bool need_initial_data = cache->buffer.empty() && _Buffer.size() <= sizeof(AuthHeader); try { auto *raw_client = client.get(); cache->pending_retrieve = std::async(std::launch::async, [raw_client, dgid]() { return raw_client->retrieve(dgid); }); if (need_initial_data) { // First fetch: wait up to 5s so we have data for the first request static constexpr auto INITIAL_TIMEOUT = std::chrono::seconds(5); if (cache->pending_retrieve.wait_for(INITIAL_TIMEOUT) == std::future_status::ready) { manifest = cache->pending_retrieve.get(); cache->last_fetch = now; cache->recovery_epoch = cur_epoch; } else { std::cerr << "[CLUSTER-BE] domain=" << _Domain << " initial retrieve timed out after 5s" << std::endl; return; } } } catch (const std::exception &e) { std::cerr << "ClusterBackend::fetchFromCluster: async launch failed: " << e.what() << std::endl; } // Don't wait — always return cached data immediately. if (!need_initial_data) { // Fire-and-forget: return cached data immediately. // Update last_fetch so we don't re-launch for at least 10s. cache->last_fetch = now; if (!cache->buffer.empty()) { Loading @@ -348,6 +367,7 @@ namespace authdb { } return; } } if (manifest.size() < sizeof(AuthHeader) + sizeof(uint32_t) + sizeof(uint32_t)) { if (!manifest.empty()) Loading Loading
src/backends/cluster.cpp +29 −9 Original line number Diff line number Diff line Loading @@ -326,20 +326,39 @@ namespace authdb { return; } } else { // No pending fetch — launch async retrieve (fire-and-forget). // Use cached data for this request; result is picked up on next call. // No pending fetch — launch async retrieve. // If the cache is empty (first fetch after startup), wait synchronously // with a timeout so the server doesn't show "waiting for peers" on every // first request. Subsequent fetches are fire-and-forget. bool need_initial_data = cache->buffer.empty() && _Buffer.size() <= sizeof(AuthHeader); try { auto *raw_client = client.get(); cache->pending_retrieve = std::async(std::launch::async, [raw_client, dgid]() { return raw_client->retrieve(dgid); }); if (need_initial_data) { // First fetch: wait up to 5s so we have data for the first request static constexpr auto INITIAL_TIMEOUT = std::chrono::seconds(5); if (cache->pending_retrieve.wait_for(INITIAL_TIMEOUT) == std::future_status::ready) { manifest = cache->pending_retrieve.get(); cache->last_fetch = now; cache->recovery_epoch = cur_epoch; } else { std::cerr << "[CLUSTER-BE] domain=" << _Domain << " initial retrieve timed out after 5s" << std::endl; return; } } } catch (const std::exception &e) { std::cerr << "ClusterBackend::fetchFromCluster: async launch failed: " << e.what() << std::endl; } // Don't wait — always return cached data immediately. if (!need_initial_data) { // Fire-and-forget: return cached data immediately. // Update last_fetch so we don't re-launch for at least 10s. cache->last_fetch = now; if (!cache->buffer.empty()) { Loading @@ -348,6 +367,7 @@ namespace authdb { } return; } } if (manifest.size() < sizeof(AuthHeader) + sizeof(uint32_t) + sizeof(uint32_t)) { if (!manifest.empty()) Loading