Move metadata to provider interface

This commit is contained in:
Kieran 2022-02-08 18:20:59 +00:00
parent 6d37b42d11
commit 3321e93478
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
7 changed files with 99 additions and 36 deletions

View File

@ -7,9 +7,9 @@ namespace VoidCat.Controllers;
[Route("d")]
public class DownloadController : Controller
{
private readonly IFileStorage _storage;
private readonly IFileStore _storage;
public DownloadController(IFileStorage storage)
public DownloadController(IFileStore storage)
{
_storage = storage;
}

View File

@ -10,9 +10,9 @@ namespace VoidCat.Controllers
[Route("upload")]
public class UploadController : Controller
{
private readonly IFileStorage _storage;
private readonly IFileStore _storage;
public UploadController(IFileStorage storage)
public UploadController(IFileStore storage)
{
_storage = storage;
}

View File

@ -16,7 +16,8 @@ services.AddControllers().AddNewtonsoftJson();
services.AddMemoryCache();
services.AddScoped<IFileStorage, LocalDiskFileIngressFactory>();
services.AddScoped<IFileMetadataStore, LocalDiskFileMetadataStore>();
services.AddScoped<IFileStore, LocalDiskFileIngressFactory>();
services.AddScoped<IStatsCollector, InMemoryStatsCollector>();
var app = builder.Build();

View File

@ -0,0 +1,12 @@
using VoidCat.Model;
namespace VoidCat.Services;
public interface IFileMetadataStore
{
Task<InternalVoidFile?> Get(Guid id);
Task Set(InternalVoidFile meta);
Task Update(VoidFile patch, Guid editSecret);
}

View File

@ -2,7 +2,7 @@
namespace VoidCat.Services
{
public interface IFileStorage
public interface IFileStore
{
Task<VoidFile?> Get(Guid id);
@ -11,5 +11,7 @@ namespace VoidCat.Services
Task Egress(Guid id, Stream outStream, CancellationToken cts);
Task UpdateInfo(VoidFile patch, Guid editSecret);
IAsyncEnumerable<VoidFile> ListFiles();
}
}

View File

@ -0,0 +1,55 @@
using Newtonsoft.Json;
using VoidCat.Model;
using VoidCat.Model.Exceptions;
namespace VoidCat.Services;
public class LocalDiskFileMetadataStore : IFileMetadataStore
{
private const string MetadataDir = "metadata";
private readonly VoidSettings _settings;
public LocalDiskFileMetadataStore(VoidSettings settings)
{
_settings = settings;
var metaPath = Path.Combine(_settings.DataDirectory, MetadataDir);
if (!Directory.Exists(metaPath))
{
Directory.CreateDirectory(metaPath);
}
}
public async Task<InternalVoidFile?> Get(Guid id)
{
var path = MapMeta(id);
if (!File.Exists(path)) throw new VoidFileNotFoundException(id);
var json = await File.ReadAllTextAsync(path);
return JsonConvert.DeserializeObject<InternalVoidFile>(json);
}
public Task Set(InternalVoidFile meta)
{
var path = MapMeta(meta.Id);
var json = JsonConvert.SerializeObject(meta);
return File.WriteAllTextAsync(path, json);
}
public async Task Update(VoidFile patch, Guid editSecret)
{
var oldMeta = await Get(patch.Id);
if (oldMeta?.EditSecret != editSecret)
{
throw new VoidNotAllowedException("Edit secret incorrect");
}
// only patch metadata
oldMeta.Metadata = patch.Metadata;
await Set(oldMeta);
}
private string MapMeta(Guid id) =>
Path.ChangeExtension(Path.Join(_settings.DataDirectory, MetadataDir, id.ToString()), ".json");
}

View File

@ -1,19 +1,21 @@
using System.Buffers;
using Newtonsoft.Json;
using VoidCat.Model;
using VoidCat.Model.Exceptions;
namespace VoidCat.Services;
public class LocalDiskFileIngressFactory : IFileStorage
public class LocalDiskFileIngressFactory : IFileStore
{
private readonly VoidSettings _settings;
private readonly IStatsCollector _stats;
private readonly IFileMetadataStore _metadataStore;
public LocalDiskFileIngressFactory(VoidSettings settings, IStatsCollector stats)
public LocalDiskFileIngressFactory(VoidSettings settings, IStatsCollector stats,
IFileMetadataStore metadataStore)
{
_settings = settings;
_stats = stats;
_metadataStore = metadataStore;
if (!Directory.Exists(_settings.DataDirectory))
{
@ -23,11 +25,7 @@ public class LocalDiskFileIngressFactory : IFileStorage
public async Task<VoidFile?> Get(Guid id)
{
var path = MapMeta(id);
if (!File.Exists(path)) throw new VoidFileNotFoundException(id);
var json = await File.ReadAllTextAsync(path);
return JsonConvert.DeserializeObject<VoidFile>(json);
return await _metadataStore.Get(id);
}
public async Task Egress(Guid id, Stream outStream, CancellationToken cts)
@ -69,36 +67,31 @@ public class LocalDiskFileIngressFactory : IFileStorage
Uploaded = DateTimeOffset.UtcNow,
EditSecret = Guid.NewGuid()
};
var mPath = MapMeta(id);
var json = JsonConvert.SerializeObject(fm);
await File.WriteAllTextAsync(mPath, json, cts);
await _metadataStore.Set(fm);
return fm;
}
public async Task UpdateInfo(VoidFile patch, Guid editSecret)
public Task UpdateInfo(VoidFile patch, Guid editSecret)
{
var path = MapMeta(patch.Id);
if (!File.Exists(path)) throw new VoidFileNotFoundException(patch.Id);
var oldJson = await File.ReadAllTextAsync(path);
var oldObj = JsonConvert.DeserializeObject<InternalVoidFile>(oldJson);
if (oldObj?.EditSecret != editSecret)
return _metadataStore.Update(patch, editSecret);
}
public async IAsyncEnumerable<VoidFile> ListFiles()
{
foreach (var fe in Directory.EnumerateFiles(_settings.DataDirectory))
{
throw new VoidNotAllowedException("Edit secret incorrect");
}
var filename = Path.GetFileNameWithoutExtension(fe);
if (!Guid.TryParse(filename, out var id)) continue;
// only patch metadata
oldObj.Metadata = patch.Metadata;
var json = JsonConvert.SerializeObject(oldObj);
await File.WriteAllTextAsync(path, json);
var meta = await _metadataStore.Get(id);
if (meta != default)
{
yield return meta;
}
}
}
private string MapPath(Guid id) =>
Path.Join(_settings.DataDirectory, id.ToString());
private string MapMeta(Guid id) =>
Path.ChangeExtension(MapPath(id), ".json");
}