using System.Text.Json; using System.Text.Json.Serialization; namespace PrivaPub.Infrastructure.Backup { // What a backup holds (manifest.json at its root): enough to check it is whole, to restore it on this host only, and to // rebuild what Mongo had (each collection's indexes). public sealed class ArchiveManifest { public const int CurrentFormat = 1; public const string FileName = "manifest.json"; public int Format { get; set; } = CurrentFormat; public string Kind { get; set; }//nightly, manual, pre-deploy, pre-restore, uploaded public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public string Host { get; set; }//BackendBaseAddress: URIs and media URLs are stored whole, so only this host can restore it public string AppCommit { get; set; } public string AppRef { get; set; } public string NewestMigration { get; set; } public int MigrationNumber { get; set; } public bool Consistent { get; set; }//read at one instant (a snapshot session on a replica set) public bool DbOnly { get; set; }//no media files, only their list (the deploy's, which can't link www-data's files) public List Collections { get; set; } = []; public List Excluded { get; set; } = []; public MediaEntry Media { get; set; } = new(); public sealed class CollectionEntry { public string Name { get; set; } public long Count { get; set; } public long Bytes { get; set; } public string Sha256 { get; set; } public List Indexes { get; set; } = [];//each as canonical Extended JSON } public sealed class ExcludedEntry { public string Name { get; set; } public string Why { get; set; } } public sealed class MediaEntry { public int Files { get; set; } public long Bytes { get; set; } public int Missing { get; set; } public List List { get; set; } = []; } static readonly JsonSerializerOptions Json = new() { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, DefaultIgnoreCondition = JsonIgnoreCondition.Never }; public static ArchiveManifest Read(string directory) { var path = Path.Combine(directory, FileName); return File.Exists(path) ? JsonSerializer.Deserialize(File.ReadAllText(path), Json) : default; } public void Write(string directory) { using var file = new FileStream(Path.Combine(directory, FileName), FileMode.Create, FileAccess.Write); JsonSerializer.Serialize(file, this, Json); file.Flush(flushToDisk: true); } } }