Files
UnrealEngine/Engine/Source/Developer/Zen/Public/Experimental/BuildServerInterface.h
2025-05-18 13:04:45 +08:00

169 lines
5.1 KiB
C++

// 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 <atomic>
#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<FBuildTransferCommand, ESPMode::ThreadSafe>
{
EBuildTransferType Type;
FCbObjectId BuildId;
FString Namespace;
FString Bucket;
FString Destination;
FString ProjectFilePath;
std::atomic<bool> 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<FBuildTransferCommand> BuildTransferCommand;
friend class UE::Zen::Build::FBuildServiceInstance;
};
typedef TUniqueFunction<void(EConnectionState)> FOnConnectionComplete;
typedef TUniqueFunction<void()> FOnRefreshNamespacesAndBucketsComplete;
typedef TUniqueFunction<void(TArray<FBuildRecord>&& 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<void()>& OnRefreshNamespacesAndBucketsComplete() { return RefreshNamespacesAndBucketsComplete; }
inline const TMultiMap<FString, FString>& 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<void(FString& CommandLineArgs)> FPreZenUtilityInvocation;
typedef TUniqueFunction<void(bool)> 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<void()> RefreshNamespacesAndBucketsComplete;
std::atomic<EConnectionState> ConnectionState = EConnectionState::NotStarted;
FCriticalSection AccessCs;
TUniquePtr<Private::FAccessToken> Access;
FTSTicker::FDelegateHandle RefreshAccessTokenHandle;
double RefreshAccessTokenTime = 0.0;
uint32 LoginAttempts = 0;
uint32 FailedLoginAttempts = 0;
uint32 InteractiveLoginAttempts = 0;
FRWLock NamespacesAndBucketsLock;
TMultiMap<FString, FString> NamespacesAndBuckets;
TMpscQueue<TSharedRef<FBuildTransferCommand>> BuildTransferThreadCommands;
FThread BuildTransferThread;
std::atomic<bool> bBuildTransferThreadStarting = false;
std::atomic<bool> bBuildTransferThreadStopping = false;
FServiceSettings Settings;
FAnsiStringBuilderBase EffectiveDomain;
};
bool LoadFromCompactBinary(FCbFieldView Field, FBuildServiceInstance::FBuildRecord& OutBuildRecord);
} // namespace UE::StorageService::Build
#undef UE_API