wabbajack/Wabbajack.Lib/ClientAPI.cs

195 lines
7.0 KiB
C#
Raw Normal View History

2020-06-01 22:27:57 +00:00
using System;
using System.Collections.Generic;
2020-07-14 12:15:01 +00:00
using System.Linq;
using System.Net;
2020-05-20 03:25:41 +00:00
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Wabbajack.Common;
using Wabbajack.Common.Exceptions;
2020-05-20 03:25:41 +00:00
using Wabbajack.Common.Serialization.Json;
using Wabbajack.Lib.Downloaders;
2020-07-14 12:15:01 +00:00
namespace Wabbajack.Lib
{
2020-07-14 12:15:01 +00:00
public static class BuildServerStatus
{
private static bool _didCheck;
private static bool _isBuildServerDown;
private static bool CheckBuildServer()
{
2020-07-14 12:44:07 +00:00
var client = new Http.Client();
2020-07-14 12:15:01 +00:00
try
{
var result = client.GetAsync($"{Consts.WabbajackBuildServerUri}heartbeat").Result;
2020-07-14 12:44:07 +00:00
_isBuildServerDown = result.StatusCode != HttpStatusCode.OK && result.StatusCode != HttpStatusCode.InternalServerError;
2020-07-14 12:15:01 +00:00
}
catch (Exception)
{
_isBuildServerDown = true;
}
finally
{
_didCheck = true;
}
Utils.Log($"Build server is {(_isBuildServerDown ? "down" : "alive")}");
return _isBuildServerDown;
}
public static bool IsBuildServerDown
{
get
{
return _didCheck ? _isBuildServerDown : CheckBuildServer();
}
}
}
2020-05-20 03:25:41 +00:00
[JsonName("ModUpgradeRequest")]
public class ModUpgradeRequest
{
public Archive OldArchive { get; set; }
public Archive NewArchive { get; set; }
public ModUpgradeRequest(Archive oldArchive, Archive newArchive)
{
OldArchive = oldArchive;
NewArchive = newArchive;
}
2020-07-13 22:10:05 +00:00
public async Task<bool> IsValid()
2020-05-20 03:25:41 +00:00
{
2020-07-13 22:10:05 +00:00
if (OldArchive.Size > 2_500_000_000 || NewArchive.Size > 2_500_000_000) return false;
if (OldArchive.Hash == NewArchive.Hash && OldArchive.State.PrimaryKeyString == NewArchive.State.PrimaryKeyString) return false;
if (OldArchive.State.GetType() != NewArchive.State.GetType())
2020-05-20 03:25:41 +00:00
return false;
2020-07-13 22:10:05 +00:00
if (OldArchive.State is IUpgradingState u)
{
return await u.ValidateUpgrade(OldArchive.Hash, NewArchive.State);
2020-05-20 03:25:41 +00:00
}
2020-07-13 22:10:05 +00:00
return false;
2020-05-20 03:25:41 +00:00
}
}
public class ClientAPI
{
2020-06-26 17:08:30 +00:00
public static async Task<Wabbajack.Lib.Http.Client> GetClient()
{
2020-06-26 17:08:30 +00:00
var client = new Wabbajack.Lib.Http.Client();
2020-06-01 22:27:57 +00:00
client.Headers.Add((Consts.MetricsKeyHeader, await Metrics.GetMetricsKey()));
return client;
}
2020-07-13 22:10:05 +00:00
public static async Task<Uri> GetModUpgrade(Archive oldArchive, Archive newArchive, TimeSpan? maxWait = null, TimeSpan? waitBetweenTries = null, bool useAuthor = false)
{
2020-05-20 03:25:41 +00:00
maxWait ??= TimeSpan.FromMinutes(10);
waitBetweenTries ??= TimeSpan.FromSeconds(15);
var request = new ModUpgradeRequest( oldArchive, newArchive);
var start = DateTime.UtcNow;
RETRY:
2020-07-13 22:10:05 +00:00
var response = await (useAuthor ? await AuthorApi.Client.GetAuthorizedClient() : await GetClient())
2020-05-20 03:25:41 +00:00
.PostAsync($"{Consts.WabbajackBuildServerUri}mod_upgrade", new StringContent(request.ToJson(), Encoding.UTF8, "application/json"));
2020-04-10 03:54:02 +00:00
if (response.IsSuccessStatusCode)
{
2020-05-20 03:25:41 +00:00
switch (response.StatusCode)
{
case HttpStatusCode.OK:
return new Uri(await response.Content.ReadAsStringAsync());
case HttpStatusCode.Accepted:
Utils.Log($"Waiting for patch processing on the server for {oldArchive.Name}, sleeping for another 15 seconds");
await Task.Delay(TimeSpan.FromSeconds(15));
response.Dispose();
if (DateTime.UtcNow - start > maxWait)
throw new HttpException(response);
goto RETRY;
}
2020-04-10 03:54:02 +00:00
}
2020-05-20 03:25:41 +00:00
var ex = new HttpException(response);
response.Dispose();
throw ex;
}
2020-03-31 22:05:36 +00:00
2020-04-02 21:16:46 +00:00
public class NexusCacheStats
{
public long CachedCount { get; set; }
public long ForwardCount { get; set; }
public double CacheRatio { get; set; }
}
public static async Task<NexusCacheStats> GetNexusCacheStats()
{
return await (await GetClient())
2020-04-02 21:16:46 +00:00
.GetJsonAsync<NexusCacheStats>($"{Consts.WabbajackBuildServerUri}nexus_cache/stats");
}
2020-06-20 22:51:47 +00:00
public static async Task SendModListDefinition(ModList modList)
{
2020-06-20 22:51:47 +00:00
var client = await GetClient();
2020-07-14 12:15:01 +00:00
if (BuildServerStatus.IsBuildServerDown)
return;
2020-06-20 22:51:47 +00:00
await client.PostAsync($"{Consts.WabbajackBuildServerUri}list_definitions/ingest", new StringContent(modList.ToJson(), Encoding.UTF8, "application/json"));
}
2020-06-14 13:13:29 +00:00
2020-06-20 22:51:47 +00:00
public static async Task<Archive[]> GetExistingGameFiles(WorkQueue queue, Game game)
2020-06-14 13:13:29 +00:00
{
2020-07-14 12:15:01 +00:00
if(BuildServerStatus.IsBuildServerDown)
return new Archive[0];
2020-06-14 13:13:29 +00:00
var client = await GetClient();
2020-06-20 22:51:47 +00:00
var metaData = game.MetaData();
var results =
await client.GetJsonAsync<Archive[]>(
$"{Consts.WabbajackBuildServerUri}game_files/{game}/{metaData.InstalledVersion}");
return (await results.PMap(queue, async file => (await file.State.Verify(file), file))).Where(f => f.Item1)
.Select(f =>
{
f.file.Name = ((GameFileSourceDownloader.State)f.file.State).GameFile.Munge().ToString();
return f.file;
})
.ToArray();
2020-06-14 13:13:29 +00:00
}
2020-06-21 22:03:54 +00:00
public static async Task<AbstractDownloadState?> InferDownloadState(Hash hash)
{
2020-07-14 12:15:01 +00:00
if (BuildServerStatus.IsBuildServerDown)
return null;
2020-06-21 22:03:54 +00:00
var client = await GetClient();
2020-07-14 12:15:01 +00:00
var results = await client.GetJsonAsync<Archive[]>(
$"{Consts.WabbajackBuildServerUri}mod_files/by_hash/{hash.ToHex()}");
2020-06-21 22:03:54 +00:00
2020-07-12 02:18:58 +00:00
await DownloadDispatcher.PrepareAll(results.Select(r => r.State));
2020-06-21 22:03:54 +00:00
foreach (var result in results)
{
2020-07-12 02:18:58 +00:00
try
{
if (await result.State.Verify(result)) return result.State;
}
catch (Exception ex)
{
Utils.Log($"Verification error for failed for inferenced archive {result.State.PrimaryKeyString}");
Utils.Log(ex.ToString());
}
2020-06-21 22:03:54 +00:00
}
return null;
}
2020-07-13 22:10:05 +00:00
public static async Task<Archive[]> GetModUpgrades(Hash src)
{
var client = await GetClient();
Utils.Log($"Looking for generic upgrade for {src} ({(long)src})");
var results = await client.GetJsonAsync<Archive[]>($"{Consts.WabbajackBuildServerUri}mod_upgrade/find/{src.ToHex()}");
return results;
}
}
}