mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Implement MongoDB based mod cleaning
This commit is contained in:
parent
717ad8c70a
commit
55f90bd485
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
@ -7,6 +8,7 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
using Nancy;
|
using Nancy;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Wabbajack.CacheServer.DTOs;
|
using Wabbajack.CacheServer.DTOs;
|
||||||
using Wabbajack.Common;
|
using Wabbajack.Common;
|
||||||
using Wabbajack.Lib.Downloaders;
|
using Wabbajack.Lib.Downloaders;
|
||||||
@ -28,10 +30,62 @@ namespace Wabbajack.CacheServer
|
|||||||
Get("/nexus_api_cache/ingest/{Folder}", HandleIngestCache);
|
Get("/nexus_api_cache/ingest/{Folder}", HandleIngestCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class UpdatedMod
|
||||||
|
{
|
||||||
|
public long mod_id;
|
||||||
|
public long latest_file_update;
|
||||||
|
public long latest_mod_activity;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<object> UpdateCache(object arg)
|
public async Task<object> UpdateCache(object arg)
|
||||||
{
|
{
|
||||||
var api = await NexusApiClient.Get(Request.Headers["apikey"].FirstOrDefault());
|
var api = await NexusApiClient.Get(Request.Headers["apikey"].FirstOrDefault());
|
||||||
await api.ClearUpdatedModsInCache();
|
|
||||||
|
var gameTasks = GameRegistry.Games.Values
|
||||||
|
.Where(game => game.NexusName != null)
|
||||||
|
.Select(async game =>
|
||||||
|
{
|
||||||
|
return (game,
|
||||||
|
mods: await api.Get<List<UpdatedMod>>(
|
||||||
|
$"https://api.nexusmods.com/v1/games/{game.NexusName}/mods/updated.json?period=1m"));
|
||||||
|
})
|
||||||
|
.Select(async rTask =>
|
||||||
|
{
|
||||||
|
var (game, mods) = await rTask;
|
||||||
|
return mods.Select(mod => new { game = game, mod = mod });
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
Utils.Log($"Getting update lits for {gameTasks.Count} games");
|
||||||
|
|
||||||
|
var purge = (await Task.WhenAll(gameTasks))
|
||||||
|
.SelectMany(i => i)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
Utils.Log($"Found {purge.Count} updated mods in the last month");
|
||||||
|
using (var queue = new WorkQueue())
|
||||||
|
{
|
||||||
|
var collected = await purge.Select(d =>
|
||||||
|
{
|
||||||
|
var a = d.mod.latest_file_update.AsUnixTime();
|
||||||
|
// Mod activity could hide files
|
||||||
|
var b = d.mod.latest_mod_activity.AsUnixTime();
|
||||||
|
|
||||||
|
return new {Game = d.game.NexusName, Date = (a > b ? a : b), ModId = d.mod.mod_id.ToString()};
|
||||||
|
}).PMap(queue, async t =>
|
||||||
|
{
|
||||||
|
var resultA = await Server.Config.NexusModInfos.Connect().DeleteManyAsync(f =>
|
||||||
|
f.Game == t.Game && f.ModId == t.ModId && f.LastCheckedUTC <= t.Date);
|
||||||
|
var resultB = await Server.Config.NexusModFiles.Connect().DeleteManyAsync(f =>
|
||||||
|
f.Game == t.Game && f.ModId == t.ModId && f.LastCheckedUTC <= t.Date);
|
||||||
|
var resultC = await Server.Config.NexusFileInfos.Connect().DeleteManyAsync(f =>
|
||||||
|
f.Game == t.Game && f.ModId == t.ModId && f.LastCheckedUTC <= t.Date);
|
||||||
|
|
||||||
|
return resultA.DeletedCount + resultB.DeletedCount + resultC.DeletedCount;
|
||||||
|
});
|
||||||
|
|
||||||
|
Utils.Log($"Purged {collected.Sum()} cache entries");
|
||||||
|
}
|
||||||
|
|
||||||
return "Done";
|
return "Done";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +229,6 @@ namespace Wabbajack.CacheServer
|
|||||||
string param = (string)arg.request;
|
string param = (string)arg.request;
|
||||||
var url = new Uri(Encoding.UTF8.GetString(param.FromHex()));
|
var url = new Uri(Encoding.UTF8.GetString(param.FromHex()));
|
||||||
|
|
||||||
Utils.Log($"{DateTime.Now} - Not Cached - {url}");
|
|
||||||
var client = new HttpClient();
|
var client = new HttpClient();
|
||||||
var builder = new UriBuilder(url) {Host = "localhost", Port = Request.Url.Port ?? 8080, Scheme = "http"};
|
var builder = new UriBuilder(url) {Host = "localhost", Port = Request.Url.Port ?? 8080, Scheme = "http"};
|
||||||
client.DefaultRequestHeaders.Add("apikey", Request.Headers["apikey"]);
|
client.DefaultRequestHeaders.Add("apikey", Request.Headers["apikey"]);
|
||||||
|
@ -353,13 +353,6 @@ namespace Wabbajack.Lib.NexusApi
|
|||||||
public string URI { get; set; }
|
public string URI { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class UpdatedMod
|
|
||||||
{
|
|
||||||
public long mod_id;
|
|
||||||
public long latest_file_update;
|
|
||||||
public long latest_mod_activity;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool? _useLocalCache;
|
private static bool? _useLocalCache;
|
||||||
public static MethodInfo CacheMethod { get; set; }
|
public static MethodInfo CacheMethod { get; set; }
|
||||||
|
|
||||||
@ -374,88 +367,5 @@ namespace Wabbajack.Lib.NexusApi
|
|||||||
}
|
}
|
||||||
set => _localCacheDir = value;
|
set => _localCacheDir = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task ClearUpdatedModsInCache()
|
|
||||||
{
|
|
||||||
if (NexusApiClient.CacheMethod == null) return;
|
|
||||||
using (var queue = new WorkQueue())
|
|
||||||
{
|
|
||||||
var invalid_json = (await Directory.EnumerateFiles(LocalCacheDir, "*.json")
|
|
||||||
.PMap(queue, f =>
|
|
||||||
{
|
|
||||||
var s = JsonSerializer.Create();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var tr = File.OpenText(f))
|
|
||||||
s.Deserialize(new JsonTextReader(tr));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (JsonReaderException)
|
|
||||||
{
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
})).Where(f => f != null).ToList();
|
|
||||||
Utils.Log($"Found {invalid_json.Count} bad json files");
|
|
||||||
foreach (var file in invalid_json)
|
|
||||||
File.Delete(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
var gameTasks = GameRegistry.Games.Values
|
|
||||||
.Where(game => game.NexusName != null)
|
|
||||||
.Select(async game =>
|
|
||||||
{
|
|
||||||
return (game,
|
|
||||||
mods: await Get<List<UpdatedMod>>(
|
|
||||||
$"https://api.nexusmods.com/v1/games/{game.NexusName}/mods/updated.json?period=1m"));
|
|
||||||
})
|
|
||||||
.Select(async rTask =>
|
|
||||||
{
|
|
||||||
var (game, mods) = await rTask;
|
|
||||||
return mods.Select(mod => new { game = game, mod = mod });
|
|
||||||
});
|
|
||||||
var purge = (await Task.WhenAll(gameTasks))
|
|
||||||
.SelectMany(i => i)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
Utils.Log($"Found {purge.Count} updated mods in the last month");
|
|
||||||
using (var queue = new WorkQueue())
|
|
||||||
{
|
|
||||||
var to_purge = (await Directory.EnumerateFiles(LocalCacheDir, "*.json")
|
|
||||||
.PMap(queue, f =>
|
|
||||||
{
|
|
||||||
Utils.Status("Cleaning Nexus cache for");
|
|
||||||
var uri = new Uri(Encoding.UTF8.GetString(Path.GetFileNameWithoutExtension(f).FromHex()));
|
|
||||||
var parts = uri.PathAndQuery.Split('/', '.').ToHashSet();
|
|
||||||
var found = purge.FirstOrDefault(p =>
|
|
||||||
parts.Contains(p.game.NexusName) && parts.Contains(p.mod.mod_id.ToString()));
|
|
||||||
if (found != null)
|
|
||||||
{
|
|
||||||
var a = found.mod.latest_file_update.AsUnixTime();
|
|
||||||
// Mod activity could hide files
|
|
||||||
var b = found.mod.latest_mod_activity.AsUnixTime();
|
|
||||||
var should_remove = File.GetLastWriteTimeUtc(f) <= (a > b ? a : b);
|
|
||||||
return (should_remove, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToDo
|
|
||||||
// Can improve to not read the entire file to see if it starts with null
|
|
||||||
if (File.ReadAllText(f).StartsWith("null"))
|
|
||||||
return (true, f);
|
|
||||||
|
|
||||||
return (false, f);
|
|
||||||
}))
|
|
||||||
.Where(p => p.Item1)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
Utils.Log($"Purging {to_purge.Count} cache entries");
|
|
||||||
await to_purge.PMap(queue, f =>
|
|
||||||
{
|
|
||||||
var uri = new Uri(Encoding.UTF8.GetString(Path.GetFileNameWithoutExtension(f.f).FromHex()));
|
|
||||||
Utils.Log($"Purging {uri}");
|
|
||||||
File.Delete(f.f);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user