2022-10-18 04:48:49 +00:00
|
|
|
|
using System.Data.SQLite;
|
2022-12-28 16:21:58 +00:00
|
|
|
|
using System.Text.Json;
|
2022-10-18 04:48:49 +00:00
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using Wabbajack.DTOs;
|
|
|
|
|
using Wabbajack.DTOs.DownloadStates;
|
2022-12-28 16:21:58 +00:00
|
|
|
|
using Wabbajack.DTOs.JsonConverters;
|
2022-10-18 04:48:49 +00:00
|
|
|
|
using Wabbajack.Hashing.xxHash64;
|
|
|
|
|
using Wabbajack.Paths;
|
|
|
|
|
using Wabbajack.Paths.IO;
|
|
|
|
|
|
|
|
|
|
namespace Wabbajack.Downloaders.VerificationCache;
|
|
|
|
|
|
|
|
|
|
public class VerificationCache : IVerificationCache, IDisposable
|
|
|
|
|
{
|
|
|
|
|
private readonly AbsolutePath _location;
|
|
|
|
|
private readonly string _connectionString;
|
|
|
|
|
private readonly SQLiteConnection _conn;
|
|
|
|
|
private readonly TimeSpan _expiry;
|
|
|
|
|
private readonly ILogger<VerificationCache> _logger;
|
2022-12-28 16:21:58 +00:00
|
|
|
|
private readonly DTOSerializer _dtos;
|
2022-10-18 04:48:49 +00:00
|
|
|
|
|
2022-12-28 16:21:58 +00:00
|
|
|
|
public VerificationCache(ILogger<VerificationCache> logger, AbsolutePath location, TimeSpan expiry, DTOSerializer dtos)
|
2022-10-18 04:48:49 +00:00
|
|
|
|
{
|
|
|
|
|
_logger = logger;
|
|
|
|
|
_location = location;
|
|
|
|
|
_expiry = expiry;
|
2022-12-28 16:21:58 +00:00
|
|
|
|
_dtos = dtos;
|
2022-10-18 04:48:49 +00:00
|
|
|
|
|
|
|
|
|
if (!_location.Parent.DirectoryExists())
|
|
|
|
|
_location.Parent.CreateDirectory();
|
|
|
|
|
|
|
|
|
|
_connectionString =
|
|
|
|
|
string.Intern($"URI=file:{_location};Pooling=True;Max Pool Size=100; Journal Mode=Memory;");
|
|
|
|
|
_conn = new SQLiteConnection(_connectionString);
|
|
|
|
|
_conn.Open();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using var cmd = new SQLiteCommand(_conn);
|
|
|
|
|
cmd.CommandText = @"CREATE TABLE IF NOT EXISTS VerficationCache (
|
|
|
|
|
PKS TEXT PRIMARY KEY,
|
2022-12-28 16:21:58 +00:00
|
|
|
|
LastModified BIGINT,
|
|
|
|
|
State TEXT)
|
2022-10-18 04:48:49 +00:00
|
|
|
|
WITHOUT ROWID";
|
|
|
|
|
cmd.ExecuteNonQuery();
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-28 16:21:58 +00:00
|
|
|
|
public async Task<(bool?, IDownloadState?)> Get(IDownloadState archive)
|
2022-10-18 04:48:49 +00:00
|
|
|
|
{
|
|
|
|
|
var key = archive.PrimaryKeyString;
|
|
|
|
|
|
|
|
|
|
await using var cmd = new SQLiteCommand(_conn);
|
2022-12-28 16:21:58 +00:00
|
|
|
|
cmd.CommandText = "SELECT LastModified, State FROM VerficationCache WHERE PKS = @pks";
|
2022-10-18 04:48:49 +00:00
|
|
|
|
cmd.Parameters.AddWithValue("@pks", key);
|
|
|
|
|
await cmd.PrepareAsync();
|
|
|
|
|
|
|
|
|
|
await using var reader = await cmd.ExecuteReaderAsync();
|
|
|
|
|
while (await reader.ReadAsync())
|
|
|
|
|
{
|
|
|
|
|
var ts = DateTime.FromFileTimeUtc(reader.GetInt64(0));
|
2022-12-28 16:21:58 +00:00
|
|
|
|
var state = JsonSerializer.Deserialize<IDownloadState>(reader.GetString(1), _dtos.Options);
|
|
|
|
|
|
|
|
|
|
return (DateTime.UtcNow - ts <= _expiry, state);
|
2022-10-18 04:48:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-12-28 16:21:58 +00:00
|
|
|
|
return (null, null);
|
2022-10-18 04:48:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task Put(IDownloadState state, bool valid)
|
|
|
|
|
{
|
|
|
|
|
var key = state.PrimaryKeyString;
|
|
|
|
|
if (valid)
|
|
|
|
|
{
|
|
|
|
|
await using var cmd = new SQLiteCommand(_conn);
|
2022-12-28 16:21:58 +00:00
|
|
|
|
cmd.CommandText = @"INSERT INTO VerficationCache (PKS, LastModified, State) VALUES (@pks, @lastModified, @state)
|
|
|
|
|
ON CONFLICT(PKS) DO UPDATE SET LastModified = @lastModified, State = @state";
|
2022-10-18 04:48:49 +00:00
|
|
|
|
cmd.Parameters.AddWithValue("@pks", key);
|
|
|
|
|
cmd.Parameters.AddWithValue("@lastModified", DateTime.UtcNow.ToFileTimeUtc());
|
2022-12-28 16:21:58 +00:00
|
|
|
|
cmd.Parameters.AddWithValue("@state", JsonSerializer.Serialize(state, _dtos.Options));
|
2022-10-18 04:48:49 +00:00
|
|
|
|
await cmd.PrepareAsync();
|
|
|
|
|
|
|
|
|
|
await cmd.ExecuteNonQueryAsync();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation("Marking {Key} as invalid", key);
|
|
|
|
|
await using var cmd = new SQLiteCommand(_conn);
|
|
|
|
|
cmd.CommandText = @"DELETE FROM VerficationCache WHERE PKS = @pks";
|
|
|
|
|
cmd.Parameters.AddWithValue("@pks", state.PrimaryKeyString);
|
|
|
|
|
await cmd.PrepareAsync();
|
|
|
|
|
await cmd.ExecuteNonQueryAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
_conn.Close();
|
|
|
|
|
_conn.Dispose();
|
|
|
|
|
}
|
|
|
|
|
}
|