Files
clio/src/cluster/CacheLoaderDecider.hpp
Sergey Kuznetsov fbdd6d6105 feat: Limit cache loading in cluster (#2985)
This PR adds an option to limit simultaneous cache loading in a cluster
to one node at a time.
Fixes #2707
2026-03-09 17:11:20 +00:00

81 lines
3.3 KiB
C++

//------------------------------------------------------------------------------
/*
This file is part of clio: https://github.com/XRPLF/clio
Copyright (c) 2026, the clio developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#pragma once
#include "cluster/Backend.hpp"
#include "cluster/ClioNode.hpp"
#include "data/LedgerCacheLoadingState.hpp"
#include <boost/asio/thread_pool.hpp>
#include <memory>
namespace cluster {
/**
* @brief Decides which node in the cluster should load the ledger cache.
*
* This class monitors cluster state changes and determines whether the current node
* should begin loading the ledger cache from the backend. The decision is made by:
* 1. Doing nothing if this node's cache is already full
* 2. Doing nothing if any node in the cluster is currently loading the cache
* 3. Sorting all nodes whose cache is not yet full by UUID for deterministic ordering
* 4. Permitting loading on this node if it is the first in the sorted list
*
* This ensures at most one node in the cluster loads the cache at a time.
*/
class CacheLoaderDecider {
/** @brief Thread pool for spawning asynchronous tasks */
boost::asio::thread_pool& ctx_;
/** @brief Interface for controlling cache loading permission of this node */
std::unique_ptr<data::LedgerCacheLoadingStateInterface> cacheLoadingState_;
public:
/**
* @brief Constructs a CacheLoaderDecider.
*
* @param ctx Thread pool for executing asynchronous operations
* @param cacheLoadingState Cache loading state interface for permitting cache load
*/
CacheLoaderDecider(
boost::asio::thread_pool& ctx,
std::unique_ptr<data::LedgerCacheLoadingStateInterface> cacheLoadingState
);
/**
* @brief Handles cluster state changes and decides whether this node should load the cache.
*
* This method is called when cluster state changes. It asynchronously:
* - Does nothing if this node's cache is already full
* - Does nothing if any node in the cluster is currently loading the cache
* - Sorts all not-yet-full nodes by UUID to establish a deterministic order
* - Permits cache loading on this node if it is first in the sorted list
*
* @param selfId The UUID of the current node
* @param clusterData Shared pointer to current cluster data; may be empty if communication
* failed
*/
void
onNewState(ClioNode::CUuid selfId, std::shared_ptr<Backend::ClusterData const> clusterData);
};
} // namespace cluster