// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Containers/Map.h" #include "Containers/MpscQueue.h" #include "Containers/StringFwd.h" #include "Containers/StringView.h" #include "Containers/Ticker.h" #include "Containers/UnrealString.h" #include "HAL/CriticalSection.h" #include "HAL/PlatformProcess.h" #include "HAL/Thread.h" #include "Serialization/CompactBinary.h" #include "Templates/Function.h" #include "Templates/SharedPointer.h" #include #define UE_API ZEN_API namespace UE { class IHttpClient; } namespace UE::Zen::Build::Private { class FAccessToken; } namespace UE::Zen::Build { struct FServiceSettings { public: UE_API bool ReadFromConfig(); UE_API bool ReadFromURL(FStringView InstanceURL); inline const FString& GetHost() const { return Host; } inline const FString& GetAuthScheme() const { return AuthScheme; } inline const FString& GetOAuthProviderIdentifier() const { return OAuthProviderIdentifier; } private: FString Host; FString AuthScheme; FString OAuthProviderIdentifier; }; class FBuildServiceInstance { public: enum class EBuildTransferStatus { Invalid, Queued, Active, Failed, Canceled, Succeeded }; private: enum class EBuildTransferType { Files, Oplog }; struct FBuildTransferCommand : public TSharedFromThis { EBuildTransferType Type; FCbObjectId BuildId; FString Namespace; FString Bucket; FString Destination; FString ProjectFilePath; std::atomic bCancelRequested = false; FRWLock Lock; FString Output; EBuildTransferStatus Status = EBuildTransferStatus::Queued; int ReturnCode; }; public: enum class EConnectionState { NotStarted, ConnectionInProgress, ConnectionSucceeded, ConnectionFailed }; struct FBuildRecord { FCbObjectId BuildId; FCbObject Metadata; }; struct FBuildTransfer { public: UE_API FString GetDescription() const; UE_API EBuildTransferStatus GetStatus() const; private: TSharedPtr BuildTransferCommand; friend class UE::Zen::Build::FBuildServiceInstance; }; typedef TUniqueFunction FOnConnectionComplete; typedef TUniqueFunction FOnRefreshNamespacesAndBucketsComplete; typedef TUniqueFunction&& ListBuildRecords)> FOnListBuildsComplete; UE_API FBuildServiceInstance(); UE_API FBuildServiceInstance(FStringView InstanceURL); UE_API virtual ~FBuildServiceInstance(); UE_API void Connect(FOnConnectionComplete&& OnConnectionComplete = {}); UE_API void RefreshNamespacesAndBuckets(FOnRefreshNamespacesAndBucketsComplete&& InOnRefreshNamespacesAndBucketsComplete = {}); [[nodiscard]] UE_API EConnectionState GetConnectionState() const; [[nodiscard]] UE_API FAnsiStringView GetEffectiveDomain() const; [[nodiscard]] UE_API TMulticastDelegateRegistration& OnRefreshNamespacesAndBucketsComplete() { return RefreshNamespacesAndBucketsComplete; } inline const TMultiMap& GetNamespacesAndBuckets() const { return NamespacesAndBuckets; } UE_API void ListBuilds(FStringView Namespace, FStringView Bucket, FOnListBuildsComplete&& InOnListBuildsComplete); UE_API FBuildTransfer StartBuildTransfer(const FCbObjectId& BuildId, FStringView DestinationFolder, FStringView Namespace, FStringView Bucket); UE_API FBuildTransfer StartOplogBuildTransfer(const FCbObjectId& BuildId, FStringView DestinationProjectId, FStringView DestinationOplogId, FStringView ProjectFilePath, FStringView Namespace, FStringView Bucket); private: typedef TUniqueFunction FPreZenUtilityInvocation; typedef TUniqueFunction FOnZenUtilityInvocationComplete; void Initialize(); bool AcquireAccessToken(); void SetAccessTokenAndUnlock(FScopeLock &Lock, FStringView Token, double RefreshDelay = 0.0); [[nodiscard]] FString GetAccessToken() const; void InvokeZenUtility(FStringView CommandlineArgs, FPreZenUtilityInvocation&& PreInvocation, FOnZenUtilityInvocationComplete&& OnComplete); void CallOnRefreshNamespacesAndBucketsComplete(FOnRefreshNamespacesAndBucketsComplete&& InOnRefreshNamespacesAndBucketsComplete); void KickBuildTransferThread(); void BuildTransferThreadLoop(); TMulticastDelegate RefreshNamespacesAndBucketsComplete; std::atomic ConnectionState = EConnectionState::NotStarted; FCriticalSection AccessCs; TUniquePtr Access; FTSTicker::FDelegateHandle RefreshAccessTokenHandle; double RefreshAccessTokenTime = 0.0; uint32 LoginAttempts = 0; uint32 FailedLoginAttempts = 0; uint32 InteractiveLoginAttempts = 0; FRWLock NamespacesAndBucketsLock; TMultiMap NamespacesAndBuckets; TMpscQueue> BuildTransferThreadCommands; FThread BuildTransferThread; std::atomic bBuildTransferThreadStarting = false; std::atomic bBuildTransferThreadStopping = false; FServiceSettings Settings; FAnsiStringBuilderBase EffectiveDomain; }; bool LoadFromCompactBinary(FCbFieldView Field, FBuildServiceInstance::FBuildRecord& OutBuildRecord); } // namespace UE::StorageService::Build #undef UE_API