#pragma once #include "cluster/ClioNode.hpp" #include "cluster/impl/RepeatedTask.hpp" #include "data/BackendInterface.hpp" #include "data/LedgerCacheLoadingState.hpp" #include "etl/WriterState.hpp" #include "util/log/Logger.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace cluster { /** * @brief Backend communication handler for cluster state synchronization. * * This class manages reading and writing cluster state information to/from the backend database. * It periodically reads the state of other nodes in the cluster and writes the current node's * state, enabling cluster-wide coordination and awareness. */ class Backend { public: /** @brief Type representing cluster data result - either a vector of nodes or an error message */ using ClusterData = std::expected, std::string>; private: util::Logger log_{"ClusterCommunication"}; std::shared_ptr backend_; std::unique_ptr writerState_; std::unique_ptr cacheLoadingState_; impl::RepeatedTask readerTask_; impl::RepeatedTask writerTask_; ClioNode::Uuid selfUuid_; boost::signals2::signal)> onNewState_; public: /** * @brief Construct a Backend communication handler. * * @param ctx The execution context for asynchronous operations * @param backend Interface to the backend database * @param writerState State indicating whether this node is writing to the database * @param cacheLoadingState State controlling whether this node is allowed to load the cache * @param readInterval How often to read cluster state from the backend * @param writeInterval How often to write this node's state to the backend */ Backend( boost::asio::thread_pool& ctx, std::shared_ptr backend, std::unique_ptr writerState, std::unique_ptr cacheLoadingState, std::chrono::steady_clock::duration readInterval, std::chrono::steady_clock::duration writeInterval ); ~Backend(); Backend(Backend&&) = delete; Backend& operator=(Backend&&) = delete; Backend(Backend const&) = delete; Backend& operator=(Backend const&) = delete; /** * @brief Start the backend read and write tasks. * * Begins periodic reading of cluster state from the backend and writing of this node's state. */ void run(); /** * @brief Stop the backend read and write tasks. * * Stops all periodic tasks and waits for them to complete. */ void stop(); /** * @brief Subscribe to new cluster state notifications. * * @tparam S Callable type accepting (ClioNode::cUUID, ClusterData) * @param s Subscriber callback to be invoked when new cluster state is available * @return A connection object that can be used to unsubscribe */ template requires std::invocable> boost::signals2::connection subscribeToNewState(S&& s) { return onNewState_.connect(s); } /** * @brief Get the UUID of this node in the cluster. * * @return The UUID of this node. */ ClioNode::CUuid selfId() const; private: ClusterData doRead(boost::asio::yield_context yield); void doWrite(); }; } // namespace cluster