// // Created by Shell on 2026-07-14. // #ifndef SEADISK_CACHED_SEAFILE_API_HPP #define SEADISK_CACHED_SEAFILE_API_HPP #include "seafile_api_interface.hpp" #include "seafile/cache/cache.hpp" namespace seafile::api { class CachedSeafileApi final : public ISeaFileApi { mutable cache::Cache file_info_cache; mutable cache::Cache dir_info_cache; mutable cache::Cache> repo_entries_cache; mutable cache::Cache account_info_cache; std::shared_ptr underlayer_api; std::chrono::seconds default_ttl = std::chrono::seconds(300); static std::string makeKey( std::string_view prefix, std::initializer_list args ) { std::string key(prefix); for (auto& arg : args) { key += ":"; key += arg; } return key; } public: explicit CachedSeafileApi(std::shared_ptr api) : underlayer_api(std::move(api)) { }; tl::expected authToken( const std::string& username, const std::string& password ) override { return underlayer_api->authToken(username, password); } tl::expected serverInfo() const override { return underlayer_api->serverInfo(); } tl::expected defaultRepo( const std::string& token, TokenType type ) const override { return underlayer_api->defaultRepo(token, type); } tl::expected repoInfo( const std::string& repo_id, const std::string& token, TokenType type ) const override { return underlayer_api->repoInfo(repo_id, token, type); } tl::expected, SeafileException> repoDir( const std::string& repo_id, const std::string& path, const std::string& token, TokenType type ) const override { const auto key = makeKey("repoDir", {repo_id, path}); if (const auto value = repo_entries_cache.get(key)) { return *value; } auto result = underlayer_api->repoDir(repo_id, path, token, type); if (result) { repo_entries_cache.put(key, result.value(), default_ttl); } return result; } tl::expected accountInfo( const std::string& token, TokenType type ) const override { if (const auto info = account_info_cache.get(token); info.has_value()) { return *info; } const auto result = underlayer_api->accountInfo(token, type); if (result) { account_info_cache.put(token, result.value(), default_ttl); } return result; } tl::expected fileDetail( const std::string& repo_id, const std::string& path, const std::string& token, TokenType type ) const override { const auto key = makeKey("file", {repo_id, path}); if (const auto value = file_info_cache.get(key)) { return *value; } auto result = underlayer_api->fileDetail(repo_id, path, token, type); if (result) { file_info_cache.put(key, result.value(), default_ttl); } return result; } tl::expected downloadFileUrl( const std::string& repo_id, const std::string& path, const std::string& token, TokenType type ) const override { return underlayer_api->downloadFileUrl(repo_id, path, token, type); } tl::expected downloadFile( const std::string& repo_id, const std::string& path, std::optional start, std::optional end, const std::string& token, TokenType type ) const override { return underlayer_api->downloadFile(repo_id, path, start, end, token, type); } tl::expected dirDetail( const std::string& repo_id, const std::string& path, const std::string& token, TokenType type ) const override { const auto key = makeKey("dir", {repo_id, path}); if (auto value = dir_info_cache.get(key)) { return *value; } auto result = underlayer_api->dirDetail(repo_id, path, token, type); if (result) { dir_info_cache.put(key, result.value(), default_ttl); } return result; } }; } #endif //SEADISK_CACHED_SEAFILE_API_HPP