void.cat/VoidCat/Services/Files/LocalDiskFileMetadataStore.cs

143 lines
4.2 KiB
C#
Raw Permalink Normal View History

2022-02-08 18:20:59 +00:00
using Newtonsoft.Json;
using VoidCat.Model;
2022-02-16 16:33:00 +00:00
using VoidCat.Services.Abstractions;
2022-02-08 18:20:59 +00:00
2022-02-22 14:20:31 +00:00
namespace VoidCat.Services.Files;
2022-02-08 18:20:59 +00:00
2022-06-08 16:17:53 +00:00
/// <inheritdoc />
2022-02-08 18:20:59 +00:00
public class LocalDiskFileMetadataStore : IFileMetadataStore
{
2022-02-17 22:10:37 +00:00
private const string MetadataDir = "metadata-v3";
2022-02-08 18:20:59 +00:00
private readonly VoidSettings _settings;
2022-02-22 14:20:31 +00:00
2022-06-13 13:35:26 +00:00
public LocalDiskFileMetadataStore(VoidSettings settings)
2022-02-08 18:20:59 +00:00
{
_settings = settings;
var metaPath = Path.Combine(_settings.DataDirectory, MetadataDir);
if (!Directory.Exists(metaPath))
{
Directory.CreateDirectory(metaPath);
}
}
2022-02-22 14:20:31 +00:00
2022-06-08 16:17:53 +00:00
/// <inheritdoc />
public ValueTask<Database.File?> Get(Guid id)
2022-02-08 18:20:59 +00:00
{
return GetMeta<Database.File>(id);
2022-02-08 18:20:59 +00:00
}
2023-11-20 15:22:12 +00:00
public ValueTask<Database.File?> GetHash(string digest)
{
throw new NotImplementedException();
}
2022-02-22 14:20:31 +00:00
2022-06-08 16:17:53 +00:00
/// <inheritdoc />
public async ValueTask<IReadOnlyList<Database.File>> Get(Guid[] ids)
2022-06-06 21:51:25 +00:00
{
var ret = new List<Database.File>();
2022-06-06 21:51:25 +00:00
foreach (var id in ids)
{
var r = await GetMeta<Database.File>(id);
2022-06-06 21:51:25 +00:00
if (r != null)
{
ret.Add(r);
}
}
return ret;
}
public ValueTask Add(Database.File f)
{
return Set(f.Id, f);
}
2022-06-06 21:51:25 +00:00
2022-06-08 16:17:53 +00:00
/// <inheritdoc />
public async ValueTask Update(Guid id, Database.File meta)
2022-03-15 10:39:36 +00:00
{
var oldMeta = await Get(id);
2022-03-15 10:39:36 +00:00
if (oldMeta == default) return;
2022-06-06 21:51:25 +00:00
2022-09-11 19:07:38 +00:00
oldMeta.Patch(meta);
2022-03-15 10:39:36 +00:00
await Set(id, oldMeta);
}
2022-06-08 16:17:53 +00:00
/// <inheritdoc />
public ValueTask<PagedResult<Database.File>> ListFiles(PagedRequest request)
2022-06-06 21:51:25 +00:00
{
async IAsyncEnumerable<Database.File> EnumerateFiles()
2022-06-06 21:51:25 +00:00
{
2022-06-08 16:17:53 +00:00
foreach (var metaFile in
Directory.EnumerateFiles(Path.Join(_settings.DataDirectory, MetadataDir), "*.json"))
2022-06-06 21:51:25 +00:00
{
var json = await File.ReadAllTextAsync(metaFile);
var meta = JsonConvert.DeserializeObject<Database.File>(json);
2022-06-06 21:51:25 +00:00
if (meta != null)
{
yield return meta;
2022-06-06 21:51:25 +00:00
}
}
}
2022-06-08 16:17:53 +00:00
var results = EnumerateFiles();
results = (request.SortBy, request.SortOrder) switch
{
(PagedSortBy.Name, PageSortOrder.Asc) => results.OrderBy(a => a.Name),
(PagedSortBy.Size, PageSortOrder.Asc) => results.OrderBy(a => a.Size),
(PagedSortBy.Date, PageSortOrder.Asc) => results.OrderBy(a => a.Uploaded),
(PagedSortBy.Name, PageSortOrder.Dsc) => results.OrderByDescending(a => a.Name),
(PagedSortBy.Size, PageSortOrder.Dsc) => results.OrderByDescending(a => a.Size),
(PagedSortBy.Date, PageSortOrder.Dsc) => results.OrderByDescending(a => a.Uploaded),
_ => results
};
return ValueTask.FromResult(new PagedResult<Database.File>
2022-06-08 16:17:53 +00:00
{
Page = request.Page,
PageSize = request.PageSize,
2023-08-24 10:53:12 +00:00
Data = results.Take(request.PageSize).Skip(request.Page * request.PageSize)
2022-06-08 16:17:53 +00:00
});
2022-06-06 21:51:25 +00:00
}
2022-06-08 16:17:53 +00:00
/// <inheritdoc />
public async ValueTask<IFileMetadataStore.StoreStats> Stats()
{
var files = await ListFiles(new(0, Int32.MaxValue));
2023-08-24 10:53:12 +00:00
var count = await files.Data.CountAsync();
var size = await files.Data.SumAsync(a => (long) a.Size);
2022-06-08 16:17:53 +00:00
return new(count, (ulong) size);
}
/// <inheritdoc />
public async ValueTask Set(Guid id, Database.File meta)
2022-02-08 18:20:59 +00:00
{
2022-02-17 15:52:49 +00:00
var path = MapMeta(id);
2022-02-08 18:20:59 +00:00
var json = JsonConvert.SerializeObject(meta);
2022-02-16 16:33:00 +00:00
await File.WriteAllTextAsync(path, json);
2022-02-08 18:20:59 +00:00
}
2022-02-22 14:20:31 +00:00
2022-06-08 16:17:53 +00:00
/// <inheritdoc />
2022-02-22 14:20:31 +00:00
public ValueTask Delete(Guid id)
{
var path = MapMeta(id);
if (File.Exists(path))
{
File.Delete(path);
}
return ValueTask.CompletedTask;
}
2022-02-17 22:48:34 +00:00
private async ValueTask<TMeta?> GetMeta<TMeta>(Guid id)
{
var path = MapMeta(id);
if (!File.Exists(path)) return default;
var json = await File.ReadAllTextAsync(path);
return JsonConvert.DeserializeObject<TMeta>(json);
}
2022-02-22 14:20:31 +00:00
2022-02-08 18:20:59 +00:00
private string MapMeta(Guid id) =>
Path.ChangeExtension(Path.Join(_settings.DataDirectory, MetadataDir, id.ToString()), ".json");
2022-06-06 21:51:25 +00:00
}