Refactored some functions

This commit is contained in:
cake
2025-11-18 04:00:53 +01:00
parent a68e9e996b
commit 6341a663f2
4 changed files with 252 additions and 114 deletions

View File

@@ -18,6 +18,7 @@ public sealed class FileCacheManager : IHostedService
public const string PenumbraPrefix = "{penumbra}";
private const int FileCacheVersion = 1;
private const string FileCacheVersionHeaderPrefix = "#lightless-file-cache-version:";
private readonly SemaphoreSlim _fileWriteSemaphore = new(1, 1);
private readonly LightlessConfigService _configService;
private readonly LightlessMediator _lightlessMediator;
private readonly string _csvPath;
@@ -169,27 +170,53 @@ public sealed class FileCacheManager : IHostedService
return CreateFileCacheEntity(fi, prefixedPath);
}
public List<FileCacheEntity> GetAllFileCaches() => _fileCaches.Values.SelectMany(v => v.Values.Where(e => e != null)).ToList();
public List<FileCacheEntity> GetAllFileCaches() => [.. _fileCaches.Values.SelectMany(v => v.Values.Where(e => e != null))];
public List<FileCacheEntity> GetAllFileCachesByHash(string hash, bool ignoreCacheEntries = false, bool validate = true)
{
List<FileCacheEntity> output = [];
if (_fileCaches.TryGetValue(hash, out var fileCacheEntities))
var output = new List<FileCacheEntity>();
if (!_fileCaches.TryGetValue(hash, out var fileCacheEntities))
return output;
foreach (var fileCache in fileCacheEntities.Values
.Where(c => !ignoreCacheEntries || !c.IsCacheEntry))
{
foreach (var fileCache in fileCacheEntities.Values.Where(c => !ignoreCacheEntries || !c.IsCacheEntry).ToList())
if (!validate)
{
if (!validate)
{
output.Add(fileCache);
}
else
{
var validated = GetValidatedFileCache(fileCache);
if (validated != null)
{
output.Add(validated);
}
}
output.Add(fileCache);
continue;
}
var validated = GetValidatedFileCache(fileCache);
if (validated != null)
output.Add(validated);
}
return output;
}
public async Task<List<FileCacheEntity>> GetAllFileCachesByHashAsync(string hash, bool ignoreCacheEntries = false, bool validate = true,CancellationToken token = default)
{
var output = new List<FileCacheEntity>();
if (!_fileCaches.TryGetValue(hash, out var fileCacheEntities))
return output;
foreach (var fileCache in fileCacheEntities.Values.Where(c => !ignoreCacheEntries || !c.IsCacheEntry))
{
token.ThrowIfCancellationRequested();
if (!validate)
{
output.Add(fileCache);
}
else
{
var validated = await GetValidatedFileCacheAsync(fileCache, token).ConfigureAwait(false);
if (validated != null)
output.Add(validated);
}
}
@@ -479,6 +506,44 @@ public sealed class FileCacheManager : IHostedService
}
}
public async Task WriteOutFullCsvAsync(CancellationToken cancellationToken = default)
{
await _fileWriteSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
var sb = new StringBuilder();
sb.AppendLine(BuildVersionHeader());
foreach (var entry in _fileCaches.Values
.SelectMany(k => k.Values)
.OrderBy(f => f.PrefixedFilePath, StringComparer.OrdinalIgnoreCase))
{
sb.AppendLine(entry.CsvEntry);
}
if (File.Exists(_csvPath))
{
File.Copy(_csvPath, CsvBakPath, overwrite: true);
}
try
{
await File.WriteAllTextAsync(_csvPath, sb.ToString(), cancellationToken).ConfigureAwait(false);
File.Delete(CsvBakPath);
}
catch
{
await File.WriteAllTextAsync(CsvBakPath, sb.ToString(), cancellationToken).ConfigureAwait(false);
}
}
finally
{
_fileWriteSemaphore.Release();
}
}
private void EnsureCsvHeaderLocked()
{
if (!File.Exists(_csvPath))
@@ -601,6 +666,13 @@ public sealed class FileCacheManager : IHostedService
return resultingFileCache;
}
private async Task<FileCacheEntity?> GetValidatedFileCacheAsync(FileCacheEntity fileCache, CancellationToken token = default)
{
var resultingFileCache = ReplacePathPrefixes(fileCache);
resultingFileCache = await ValidateAsync(resultingFileCache, token).ConfigureAwait(false);
return resultingFileCache;
}
private FileCacheEntity ReplacePathPrefixes(FileCacheEntity fileCache)
{
if (fileCache.PrefixedFilePath.StartsWith(PenumbraPrefix, StringComparison.OrdinalIgnoreCase))
@@ -623,6 +695,7 @@ public sealed class FileCacheManager : IHostedService
RemoveHashedFile(fileCache.Hash, fileCache.PrefixedFilePath);
return null;
}
var file = new FileInfo(fileCache.ResolvedFilepath);
if (!file.Exists)
{
@@ -630,7 +703,8 @@ public sealed class FileCacheManager : IHostedService
return null;
}
if (!string.Equals(file.LastWriteTimeUtc.Ticks.ToString(CultureInfo.InvariantCulture), fileCache.LastModifiedDateTicks, StringComparison.Ordinal))
var lastWriteTicks = file.LastWriteTimeUtc.Ticks.ToString(CultureInfo.InvariantCulture);
if (!string.Equals(lastWriteTicks, fileCache.LastModifiedDateTicks, StringComparison.Ordinal))
{
UpdateHashedFile(fileCache);
}
@@ -638,6 +712,33 @@ public sealed class FileCacheManager : IHostedService
return fileCache;
}
private async Task<FileCacheEntity?> ValidateAsync(FileCacheEntity fileCache, CancellationToken token)
{
if (string.IsNullOrWhiteSpace(fileCache.ResolvedFilepath))
{
_logger.LogWarning("FileCacheEntity has empty ResolvedFilepath for hash {hash}, prefixed path {prefixed}", fileCache.Hash, fileCache.PrefixedFilePath);
RemoveHashedFile(fileCache.Hash, fileCache.PrefixedFilePath);
return null;
}
return await Task.Run(() =>
{
var file = new FileInfo(fileCache.ResolvedFilepath);
if (!file.Exists)
{
RemoveHashedFile(fileCache.Hash, fileCache.PrefixedFilePath);
return null;
}
if (!string.Equals(file.LastWriteTimeUtc.Ticks.ToString(CultureInfo.InvariantCulture), fileCache.LastModifiedDateTicks, StringComparison.Ordinal))
{
UpdateHashedFile(fileCache);
}
return fileCache;
}, token).ConfigureAwait(false);
}
public async Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Starting FileCacheManager");
@@ -811,7 +912,7 @@ public sealed class FileCacheManager : IHostedService
if (rewriteRequired)
{
WriteOutFullCsv();
await WriteOutFullCsvAsync(cancellationToken).ConfigureAwait(false);
}
}
@@ -822,7 +923,7 @@ public sealed class FileCacheManager : IHostedService
public async Task StopAsync(CancellationToken cancellationToken)
{
WriteOutFullCsv();
await WriteOutFullCsvAsync(cancellationToken).ConfigureAwait(false);
await Task.CompletedTask.ConfigureAwait(false);
}
}