#pragma once #include #include #include #include #include #include #include #include #include class DatabaseManager { public: static DatabaseManager &GetInstance(); bool Init(boost::asio::io_context &io_context, const std::string &host, uint16_t port, const std::string &user, const std::string &password, const std::string &db); struct UserData { std::string nickname; uint64_t gold; uint32_t swordLevel; uint32_t maxSwordLevel; }; struct RankingResult { struct Entry { uint32_t rank; std::string nickname; uint64_t value; }; std::vector topEntries; int32_t myRank; uint64_t myValue; }; class ConnectionProxy { public: ConnectionProxy(std::unique_ptr conn, DatabaseManager &owner) : conn_(std::move(conn)), owner_(owner) {} ~ConnectionProxy(); // Move only ConnectionProxy(ConnectionProxy &&other) noexcept : conn_(std::move(other.conn_)), owner_(other.owner_) {} ConnectionProxy &operator=(ConnectionProxy &&other) noexcept { if (this != &other) { conn_ = std::move(other.conn_); } return *this; } ConnectionProxy(const ConnectionProxy &) = delete; ConnectionProxy &operator=(const ConnectionProxy &) = delete; boost::mysql::tcp_ssl_connection *operator->() { return conn_.get(); } boost::mysql::tcp_ssl_connection &operator*() { return *conn_; } private: std::unique_ptr conn_; DatabaseManager &owner_; }; boost::asio::awaitable LoadUser(std::string nickname); boost::asio::awaitable SaveUser(std::string nickname, uint64_t gold, uint32_t swordLevel); boost::asio::awaitable GetRanking(int type, std::string nickname); boost::asio::awaitable GetConnection(); private: DatabaseManager() = default; void ReturnConnection(std::unique_ptr conn); boost::asio::awaitable> CreateNewConnection(); std::deque> pool_; std::queue> waiting_queue_; boost::asio::io_context *io_context_ = nullptr; std::unique_ptr> strand_; boost::asio::ssl::context ssl_ctx_{boost::asio::ssl::context::tlsv12_client}; std::string host_, user_, password_, db_; uint16_t port_; uint32_t max_connections_ = 10; uint32_t current_total_connections_ = 0; };