// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include #include #include #include #include #include #include #include #include #include #include #include struct ZenCacheValue; namespace cpr { class Session; } namespace zen { class CbObjectView; class CloudCacheClient; class IoBuffer; struct IoHash; /** * Cached access token, for use with `Authorization:` header */ struct CloudCacheAccessToken { using Clock = std::chrono::system_clock; using TimePoint = Clock::time_point; static constexpr int64_t ExpireMarginInSeconds = 30; std::string Value; TimePoint ExpireTime; bool IsValid() const { return Value.empty() == false && ExpireMarginInSeconds < std::chrono::duration_cast(ExpireTime - Clock::now()).count(); } }; struct CloudCacheResult { IoBuffer Response; uint64_t SentBytes{}; uint64_t ReceivedBytes{}; double ElapsedSeconds{}; int32_t ErrorCode{}; std::string Reason; bool Success = false; }; struct PutRefResult : CloudCacheResult { std::vector Needs; IoHash RawHash; }; struct FinalizeRefResult : CloudCacheResult { std::vector Needs; }; struct CloudCacheExistsResult : CloudCacheResult { std::set Needs; }; struct GetObjectReferencesResult : CloudCacheResult { std::set References; }; /** * Context for performing Jupiter operations * * Maintains an HTTP connection so that subsequent operations don't need to go * through the whole connection setup process * */ class CloudCacheSession { public: CloudCacheSession(CloudCacheClient* CacheClient); ~CloudCacheSession(); CloudCacheResult Authenticate(); CloudCacheResult GetRef(std::string_view Namespace, std::string_view BucketId, const IoHash& Key, ZenContentType RefType); CloudCacheResult GetBlob(std::string_view Namespace, const IoHash& Key); CloudCacheResult GetCompressedBlob(std::string_view Namespace, const IoHash& Key, std::filesystem::path TempFolderPath = {}); CloudCacheResult GetObject(std::string_view Namespace, const IoHash& Key); CloudCacheResult GetInlineBlob(std::string_view Namespace, std::string_view BucketId, const IoHash& Key, IoHash& OutPayloadHash, std::filesystem::path TempFolderPath = {}); PutRefResult PutRef(std::string_view Namespace, std::string_view BucketId, const IoHash& Key, IoBuffer Ref, ZenContentType RefType); CloudCacheResult PutBlob(std::string_view Namespace, const IoHash& Key, IoBuffer Blob); CloudCacheResult PutCompressedBlob(std::string_view Namespace, const IoHash& Key, IoBuffer Blob); CloudCacheResult PutCompressedBlob(std::string_view Namespace, const IoHash& Key, const CompositeBuffer& Blob); CloudCacheResult PutObject(std::string_view Namespace, const IoHash& Key, IoBuffer Object); FinalizeRefResult FinalizeRef(std::string_view Namespace, std::string_view BucketId, const IoHash& Key, const IoHash& RefHah); CloudCacheResult RefExists(std::string_view Namespace, std::string_view BucketId, const IoHash& Key); GetObjectReferencesResult GetObjectReferences(std::string_view Namespace, const IoHash& Key); CloudCacheResult BlobExists(std::string_view Namespace, const IoHash& Key); CloudCacheResult CompressedBlobExists(std::string_view Namespace, const IoHash& Key); CloudCacheResult ObjectExists(std::string_view Namespace, const IoHash& Key); CloudCacheExistsResult BlobExists(std::string_view Namespace, const std::set& Keys); CloudCacheExistsResult CompressedBlobExists(std::string_view Namespace, const std::set& Keys); CloudCacheExistsResult ObjectExists(std::string_view Namespace, const std::set& Keys); std::vector Filter(std::string_view Namespace, std::string_view BucketId, const std::vector& ChunkHashes); CloudCacheClient& Client() { return *m_CacheClient; }; private: inline LoggerRef Log() { return m_Log; } CloudCacheResult CacheTypeExists(std::string_view Namespace, std::string_view TypeId, const IoHash& Key); CloudCacheExistsResult CacheTypeExists(std::string_view Namespace, std::string_view TypeId, const std::set& Keys); LoggerRef m_Log; RefPtr m_CacheClient; }; /** * Access token provider interface */ class CloudCacheTokenProvider { public: virtual ~CloudCacheTokenProvider() = default; virtual CloudCacheAccessToken AcquireAccessToken() = 0; static std::unique_ptr CreateFromStaticToken(CloudCacheAccessToken Token); struct OAuthClientCredentialsParams { std::string_view Url; std::string_view ClientId; std::string_view ClientSecret; }; static std::unique_ptr CreateFromOAuthClientCredentials(const OAuthClientCredentialsParams& Params); static std::unique_ptr CreateFromCallback(std::function&& Callback); }; struct CloudCacheClientOptions { std::string_view Name; std::string_view ServiceUrl; std::string_view DdcNamespace; std::string_view BlobStoreNamespace; std::string_view ComputeCluster; std::chrono::milliseconds ConnectTimeout{5000}; std::chrono::milliseconds Timeout{}; bool AssumeHttp2 = false; bool AllowResume = false; uint8_t RetryCount = 0; }; /** * Jupiter upstream cache client */ class CloudCacheClient : public RefCounted { public: CloudCacheClient(const CloudCacheClientOptions& Options, std::unique_ptr TokenProvider); ~CloudCacheClient(); std::string_view DefaultDdcNamespace() const { return m_DefaultDdcNamespace; } std::string_view DefaultBlobStoreNamespace() const { return m_DefaultBlobStoreNamespace; } std::string_view ComputeCluster() const { return m_ComputeCluster; } std::string_view ServiceUrl() const { return m_HttpClient.GetBaseUri(); } LoggerRef Logger() { return m_Log; } private: LoggerRef m_Log; const std::string m_DefaultDdcNamespace; const std::string m_DefaultBlobStoreNamespace; const std::string m_ComputeCluster; const std::unique_ptr m_TokenProvider; HttpClient m_HttpClient; friend class CloudCacheSession; }; } // namespace zen