From 3dc8883c6f8cc610c426a6436adaa5b57daa0df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Blin?= <sebastien.blin@savoirfairelinux.com> Date: Wed, 15 May 2024 17:01:24 -0400 Subject: [PATCH] conversation_module: add a fallback if the clone fails This fix testAddAcceptOfflineThenConnects without reverting 7463a8a266486c1ac3ec441a0ec175e4536af213 The idea is in case of a sporadic clone failure (peer offline but present, socket broken while cloning, etc), we schedule a new clone operation later. GitLab: #991 Change-Id: Ifacd6bfe383902bff6cb818e41ff8f5ddd0f6917 --- src/jamidht/conversation_module.cpp | 56 ++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/src/jamidht/conversation_module.cpp b/src/jamidht/conversation_module.cpp index 72ff806939..db16c086d1 100644 --- a/src/jamidht/conversation_module.cpp +++ b/src/jamidht/conversation_module.cpp @@ -51,19 +51,27 @@ struct PendingConversationFetch std::shared_ptr<dhtnet::ChannelSocket> socket {}; }; +constexpr std::chrono::seconds MAX_FALLBACK {12 * 3600s}; + struct SyncedConversation { std::mutex mtx; + std::unique_ptr<asio::steady_timer> fallbackClone; + std::chrono::seconds fallbackTimer {5s}; ConvInfo info; std::unique_ptr<PendingConversationFetch> pending; std::shared_ptr<Conversation> conversation; SyncedConversation(const std::string& convId) : info {convId} - {} + { + fallbackClone = std::make_unique<asio::steady_timer>(*Manager::instance().ioContext()); + } SyncedConversation(const ConvInfo& info) : info {info} - {} + { + fallbackClone = std::make_unique<asio::steady_timer>(*Manager::instance().ioContext()); + } bool startFetch(const std::string& deviceId, bool checkIfConv = false) { @@ -410,6 +418,7 @@ public: const std::string& deviceId, const std::string& oldConvId = ""); void bootstrap(const std::string& convId); + void fallbackClone(const asio::error_code& ec, const std::string& conversationId); void cloneConversationFrom(const std::string& conversationId, const std::string& uri, const std::string& oldConvId = ""); @@ -845,7 +854,17 @@ ConversationModule::Impl::handlePendingConversation(const std::string& conversat } } } catch (const std::exception& e) { - JAMI_WARN("Something went wrong when cloning conversation: %s", e.what()); + JAMI_WARNING("Something went wrong when cloning conversation: {}. Re-clone in {}s", e.what(), conv->fallbackTimer.count()); + conv->fallbackClone->expires_at(std::chrono::steady_clock::now() + conv->fallbackTimer); + conv->fallbackTimer *= 2; + if (conv->fallbackTimer > MAX_FALLBACK) + conv->fallbackTimer = MAX_FALLBACK; + conv->fallbackClone->async_wait( + std::bind(&ConversationModule::Impl::fallbackClone, + shared_from_this(), + std::placeholders::_1, + conversationId)); + } lk.lock(); erasePending(); @@ -1306,6 +1325,18 @@ ConversationModule::Impl::cloneConversationFrom(const std::shared_ptr<SyncedConv return true; } else { conv->stopFetch(deviceId); + JAMI_WARNING("Clone failed. Re-clone in {}s", conv->fallbackTimer.count()); + conv->fallbackClone->expires_at(std::chrono::steady_clock::now() + conv->fallbackTimer); + conv->fallbackTimer *= 2; + if (conv->fallbackTimer > MAX_FALLBACK) + conv->fallbackTimer = MAX_FALLBACK; + conv->fallbackClone->async_wait( + std::bind(&ConversationModule::Impl::fallbackClone, + sthis, + std::placeholders::_1, + conversationId)); + + } } return false; @@ -1313,6 +1344,20 @@ ConversationModule::Impl::cloneConversationFrom(const std::shared_ptr<SyncedConv MIME_TYPE_GIT); } +void +ConversationModule::Impl::fallbackClone(const asio::error_code& ec, const std::string& conversationId) +{ + if (ec == asio::error::operation_aborted) + return; + auto conv = getConversation(conversationId); + if (!conv || conv->conversation) + return; + auto members = getConversationMembers(conversationId); + for (const auto& member : members) + if (member.at("uri") != username_) + cloneConversationFrom(conversationId, member.at("uri")); +} + void ConversationModule::Impl::bootstrap(const std::string& convId) { @@ -2289,11 +2334,6 @@ ConversationModule::syncConversations(const std::string& peer, const std::string if (conv->conversation) { if (!conv->conversation->isRemoving() && conv->conversation->isMember(peer, false)) { toFetch.emplace(conv->info.id); - // TODO connect to Swarm - // if (!conv->conversation->hasSwarmChannel(deviceId)) { - // if (auto acc = pimpl_->account_.lock()) { - // } - // } } } else if (!conv->info.isRemoved() && std::find(conv->info.members.begin(), conv->info.members.end(), peer) -- GitLab