wabbajack/Wabbajack.Services.OSIntegrated/Services/ModListDownloadMaintainer.cs

97 lines
3.4 KiB
C#
Raw Permalink Normal View History

2021-12-27 15:37:20 +00:00
using System;
using System.Reactive.Subjects;
using System.Text.Json;
2021-12-27 15:37:20 +00:00
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Wabbajack.Common;
using Wabbajack.Downloaders;
using Wabbajack.DTOs;
using Wabbajack.DTOs.JsonConverters;
2021-12-27 15:37:20 +00:00
using Wabbajack.Paths;
using Wabbajack.Paths.IO;
using Wabbajack.RateLimiter;
using Wabbajack.VFS;
namespace Wabbajack.Services.OSIntegrated.Services;
public class ModListDownloadMaintainer
{
private readonly ILogger<ModListDownloadMaintainer> _logger;
private readonly Configuration _configuration;
private readonly DownloadDispatcher _dispatcher;
private readonly FileHashCache _hashCache;
private readonly IResource<DownloadDispatcher> _rateLimiter;
2021-12-30 00:15:37 +00:00
private int _downloadingCount;
private readonly DTOSerializer _dtos;
2021-12-27 15:37:20 +00:00
public ModListDownloadMaintainer(ILogger<ModListDownloadMaintainer> logger, Configuration configuration,
DownloadDispatcher dispatcher, FileHashCache hashCache, DTOSerializer dtos, IResource<DownloadDispatcher> rateLimiter)
2021-12-27 15:37:20 +00:00
{
_logger = logger;
_configuration = configuration;
_dispatcher = dispatcher;
_hashCache = hashCache;
_rateLimiter = rateLimiter;
2021-12-30 00:15:37 +00:00
_downloadingCount = 0;
_dtos = dtos;
2021-12-27 15:37:20 +00:00
}
public AbsolutePath ModListPath(ModlistMetadata metadata)
{
2022-03-30 03:39:48 +00:00
return _configuration.ModListsDownloadLocation.Combine(metadata.NamespacedName.Replace("/", "_@@_")).WithExtension(Ext.Wabbajack);
2021-12-27 15:37:20 +00:00
}
public async Task<bool> HaveModList(ModlistMetadata metadata, CancellationToken? token = null)
{
token ??= CancellationToken.None;
var path = ModListPath(metadata);
if (!path.FileExists()) return false;
2022-10-01 05:21:58 +00:00
if (await _hashCache.TryGetHashCache(path) == metadata.DownloadMetadata!.Hash) return true;
2021-12-30 00:15:37 +00:00
if (_downloadingCount > 0) return false;
2021-12-27 15:37:20 +00:00
return await _hashCache.FileHashCachedAsync(path, token.Value) == metadata.DownloadMetadata!.Hash;
}
public (IObservable<Percent> Progress, Task Task) DownloadModlist(ModlistMetadata metadata, CancellationToken token)
2021-12-27 15:37:20 +00:00
{
var path = ModListPath(metadata);
2021-12-27 15:37:20 +00:00
var progress = new Subject<Percent>();
progress.OnNext(Percent.Zero);
var tsk = Task.Run(async () =>
{
2021-12-27 15:43:10 +00:00
try
2021-12-27 15:37:20 +00:00
{
2021-12-30 00:15:37 +00:00
Interlocked.Increment(ref _downloadingCount);
using var job = await _rateLimiter.Begin($"Downloading {metadata.Title}", metadata.DownloadMetadata!.Size,
token);
2021-12-27 15:43:10 +00:00
job.OnUpdate += (_, pr) => { progress.OnNext(pr.Progress); };
var hash = await _dispatcher.Download(new Archive()
{
State = _dispatcher.Parse(new Uri(metadata.Links.Download))!,
Size = metadata.DownloadMetadata.Size,
Hash = metadata.DownloadMetadata.Hash
}, path, job, token);
if (token.IsCancellationRequested)
{
return;
}
2021-12-27 15:37:20 +00:00
2022-10-01 05:21:58 +00:00
await _hashCache.FileHashWriteCache(path, hash);
await path.WithExtension(Ext.MetaData).WriteAllTextAsync(JsonSerializer.Serialize(metadata), token);
2021-12-27 15:43:10 +00:00
}
finally
2021-12-27 15:37:20 +00:00
{
2021-12-27 15:43:10 +00:00
progress.OnCompleted();
2021-12-30 00:15:37 +00:00
Interlocked.Decrement(ref _downloadingCount);
2021-12-27 15:43:10 +00:00
}
}, token);
2021-12-27 15:37:20 +00:00
return (progress, tsk);
}
}