From b737ae27832859a136277549f4c1532bc1deac1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Blin?= <sebastien.blin@savoirfairelinux.com> Date: Wed, 21 Feb 2024 11:10:19 -0500 Subject: [PATCH] conversation: fix some bootstrap path Sometimes, failed wasn't called Change-Id: I7734518a5d186b45a6d82da14bd20948ec0976f9 --- src/jamidht/conversation.cpp | 76 +++++++++++++++++------------ src/jamidht/conversation_module.cpp | 1 + 2 files changed, 47 insertions(+), 30 deletions(-) diff --git a/src/jamidht/conversation.cpp b/src/jamidht/conversation.cpp index d181585748..3c5bf49484 100644 --- a/src/jamidht/conversation.cpp +++ b/src/jamidht/conversation.cpp @@ -2154,9 +2154,10 @@ void Conversation::checkBootstrapMember(const asio::error_code& ec, std::vector<std::map<std::string, std::string>> members) { + if (ec == asio::error::operation_aborted) + return; auto acc = pimpl_->account_.lock(); - if (ec == asio::error::operation_aborted - or pimpl_->swarmManager_->getRoutingTable().getNodes().size() > 0 or not acc) + if (pimpl_->swarmManager_->getRoutingTable().getNodes().size() > 0 or not acc) return; // We bootstrap the DRT with devices who already wrote in the repository. // However, in a conversation, a large number of devices may just watch @@ -2170,15 +2171,18 @@ Conversation::checkBootstrapMember(const asio::error_code& ec, && pimpl_->checkedMembers_.find(uri) == pimpl_->checkedMembers_.end()) break; } - // If members is empty, we finished the fallback un-successfully - if (members.empty() && uri.empty()) { + auto fallbackFailed = [](auto sthis) { JAMI_WARNING("{}[SwarmManager {}] Bootstrap: Fallback failed. Wait for remote connections.", - pimpl_->toString(), - fmt::ptr(pimpl_->swarmManager_.get())); + sthis->pimpl_->toString(), + fmt::ptr(sthis->pimpl_->swarmManager_.get())); #ifdef LIBJAMI_TESTABLE - if (pimpl_->bootstrapCbTest_) - pimpl_->bootstrapCbTest_(id(), BootstrapStatus::FAILED); + if (sthis->pimpl_->bootstrapCbTest_) + sthis->pimpl_->bootstrapCbTest_(sthis->id(), BootstrapStatus::FAILED); #endif + }; + // If members is empty, we finished the fallback un-successfully + if (members.empty() && uri.empty()) { + fallbackFailed(this); return; } @@ -2194,7 +2198,7 @@ Conversation::checkBootstrapMember(const asio::error_code& ec, devices->emplace_back(dev->getLongId()); } }, - [w = weak(), devices, members = std::move(members), uri](bool ok) { + [w = weak(), devices, members = std::move(members), uri, fallbackFailed=std::move(fallbackFailed)](bool ok) { auto sthis = w.lock(); if (!sthis) return; @@ -2219,6 +2223,9 @@ Conversation::checkBootstrapMember(const asio::error_code& ec, sthis, std::placeholders::_1, std::move(members))); + } else { + // In this case, all members are checked. Fallback failed + fallbackFailed(sthis); } }); } @@ -2241,9 +2248,33 @@ Conversation::bootstrap(std::function<void()> onBootstraped, fmt::ptr(pimpl_->swarmManager_.get()), devices.size()); // set callback - pimpl_->swarmManager_->onConnectionChanged([w = weak()](bool ok) { + auto fallback = [](auto sthis, bool now = false) { + // Fallback + auto acc = sthis->pimpl_->account_.lock(); + if (!acc) + return; + auto members = sthis->getMembers(false, false); + std::shuffle(members.begin(), members.end(), acc->rand); + if (now) { + sthis->pimpl_->fallbackTimer_->expires_at(std::chrono::steady_clock::now()); + } else { + auto timeForBootstrap = std::min(static_cast<size_t>(8), members.size()); + sthis->pimpl_->fallbackTimer_->expires_at(std::chrono::steady_clock::now() + 20s + - std::chrono::seconds(timeForBootstrap)); + JAMI_DEBUG("{}[SwarmManager {}] Fallback in {} seconds", + sthis->pimpl_->toString(), + fmt::ptr(sthis->pimpl_->swarmManager_.get()), + (20 - timeForBootstrap)); + } + sthis->pimpl_->fallbackTimer_->async_wait(std::bind(&Conversation::checkBootstrapMember, + sthis, + std::placeholders::_1, + std::move(members))); + }; + + pimpl_->swarmManager_->onConnectionChanged([w = weak(), fallback](bool ok) { // This will call methods from accounts, so trigger on another thread. - dht::ThreadPool::io().run([w, ok] { + dht::ThreadPool::io().run([w, ok, fallback=std::move(fallback)] { auto sthis = w.lock(); if (!sthis) return; @@ -2258,28 +2289,13 @@ Conversation::bootstrap(std::function<void()> onBootstraped, #endif return; } - // Fallback - auto acc = sthis->pimpl_->account_.lock(); - if (!acc) - return; - auto members = sthis->getMembers(false, false); - std::shuffle(members.begin(), members.end(), acc->rand); - // TODO decide a formula - auto timeForBootstrap = std::min(static_cast<size_t>(8), members.size()); - JAMI_DEBUG("{}[SwarmManager {}] Fallback in {} seconds", - sthis->pimpl_->toString(), - fmt::ptr(sthis->pimpl_->swarmManager_.get()), - (20 - timeForBootstrap)); - sthis->pimpl_->fallbackTimer_->expires_at(std::chrono::steady_clock::now() + 20s - - std::chrono::seconds(timeForBootstrap)); - sthis->pimpl_->fallbackTimer_->async_wait(std::bind(&Conversation::checkBootstrapMember, - sthis, - std::placeholders::_1, - std::move(members))); + fallback(sthis); }); }); pimpl_->checkedMembers_.clear(); - pimpl_->swarmManager_->setKnownNodes(devices); + if (!pimpl_->swarmManager_->setKnownNodes(devices)) { + fallback(this, true); + } } std::vector<std::string> diff --git a/src/jamidht/conversation_module.cpp b/src/jamidht/conversation_module.cpp index c18d47c40a..b915ff0d20 100644 --- a/src/jamidht/conversation_module.cpp +++ b/src/jamidht/conversation_module.cpp @@ -1240,6 +1240,7 @@ ConversationModule::Impl::bootstrap(const std::string& convId) if (auto acc = account_.lock()) for (const auto& [id, _] : acc->getKnownDevices()) kd.emplace_back(id); + auto bootstrap = [&](auto& conv) { if (conv) { #ifdef LIBJAMI_TESTABLE -- GitLab