// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Threading;
using System.Threading.Tasks;
using EpicGames.Horde.Artifacts;
using EpicGames.Horde.Compute;
using EpicGames.Horde.Logs;
using EpicGames.Horde.Projects;
using EpicGames.Horde.Secrets;
using EpicGames.Horde.Storage;
using EpicGames.Horde.Tools;
using Grpc.Core;
using Microsoft.Extensions.Logging;
namespace EpicGames.Horde
{
///
/// Interface for Horde functionality.
///
public interface IHordeClient
{
///
/// URL of the horde server
///
Uri ServerUrl { get; }
///
/// Accessor for the artifact collection
///
IArtifactCollection Artifacts { get; }
///
/// Accessor for the compute client
///
IComputeClient Compute { get; }
///
/// Accessor for the project collection
///
IProjectCollection Projects { get; }
///
/// Accessor for the secret collection
///
ISecretCollection Secrets { get; }
///
/// Accessor for the tools collection
///
IToolCollection Tools { get; }
///
/// Event triggered whenever the access token state changes
///
event Action? OnAccessTokenStateChanged;
///
/// Connect to the Horde server
///
/// Whether to allow prompting for credentials
/// Cancellation token for the operation
/// True if the connection succeded
Task LoginAsync(bool interactive, CancellationToken cancellationToken);
///
/// Gets the current connection state
///
bool HasValidAccessToken();
///
/// Gets an access token for the server
///
Task GetAccessTokenAsync(bool interactive, CancellationToken cancellationToken = default);
///
/// Gets a gRPC client interface
///
Task CreateGrpcClientAsync(CancellationToken cancellationToken = default) where TClient : ClientBase;
///
/// Creates a Horde HTTP client
///
HordeHttpClient CreateHttpClient();
///
/// Creates a storage namespace for the given base path
///
IStorageNamespace GetStorageNamespace(string relativePath, string? accessToken = null);
///
/// Creates a logger device that writes data to the server
///
IServerLogger CreateServerLogger(LogId logId, LogLevel minimumLevel = LogLevel.Information);
}
///
/// Interface for a Horde client with a known lifetime
///
public interface IHordeClientWithLifetime : IHordeClient, IAsyncDisposable
{
}
///
/// Extension methods for
///
public static class HordeClientExtensions
{
///
/// Creates a storage namespace for a particular id
///
public static IStorageNamespace GetStorageNamespace(this IHordeClient hordeClient, NamespaceId namespaceId, string? accessToken = null)
=> hordeClient.GetStorageNamespace($"api/v1/storage/{namespaceId}", accessToken);
///
/// Creates a storage namespace for a particular artifact
///
public static IStorageNamespace GetStorageNamespace(this IHordeClient hordeClient, ArtifactId artifactId)
=> hordeClient.GetStorageNamespace($"api/v2/artifacts/{artifactId}");
///
/// Creates a storage namespace for a particular log
///
public static IStorageNamespace GetStorageNamespace(this IHordeClient hordeClient, LogId logId)
=> hordeClient.GetStorageNamespace($"api/v1/logs/{logId}");
///
/// Creates a storage namespace for a particular tool
///
public static IStorageNamespace GetStorageNamespace(this IHordeClient hordeClient, ToolId toolId)
=> hordeClient.GetStorageNamespace($"api/v1/tools/{toolId}");
///
/// Reads a blob storage ref from a path
///
public static async Task TryReadRefAsync(this IHordeClient hordeClient, string path, RefCacheTime cacheTime = default, CancellationToken cancellationToken = default)
{
ReadRefResponse? response = await hordeClient.CreateHttpClient().TryReadRefAsync(path, cacheTime, cancellationToken);
if (response == null)
{
return null;
}
IStorageNamespace storageNamespace = hordeClient.GetStorageNamespace(response.BasePath);
return storageNamespace.CreateBlobRef(response.Target);
}
///
/// Reads a typed blob storage ref from a path
///
public static async Task?> TryReadRefAsync(this IHordeClient hordeClient, string path, RefCacheTime cacheTime = default, CancellationToken cancellationToken = default)
{
IBlobRef? blobRef = await hordeClient.TryReadRefAsync(path, cacheTime, cancellationToken);
return blobRef?.ForType();
}
}
}