// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschraenkt) // All rights reserved. Licensed under the MIT license. // ========================================================================== using System; using System.IO; using System.IO.Compression; using System.Threading.Tasks; using Squidex.Domain.Apps.Entities.Backup.Helpers; using Squidex.Domain.Apps.Entities.Backup.Model; using Squidex.Infrastructure; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json; using Squidex.Infrastructure.States; #pragma warning disable SA1401 // Fields must be private namespace Squidex.Domain.Apps.Entities.Backup { public class BackupReader : DisposableObjectBase, IBackupReader { private readonly ZipArchive archive; private readonly IJsonSerializer serializer; private int readEvents; private int readAttachments; public int ReadEvents { get { return readEvents; } } public int ReadAttachments { get { return readAttachments; } } public BackupReader(IJsonSerializer serializer, Stream stream) { Guard.NotNull(serializer, nameof(serializer)); this.serializer = serializer; archive = new ZipArchive(stream, ZipArchiveMode.Read, false); } protected override void DisposeObject(bool disposing) { if (disposing) { archive.Dispose(); } } public Task ReadJsonAsync(string name) { Guard.NotNullOrEmpty(name, nameof(name)); var entry = GetEntry(name); using (var stream = entry.Open()) { return Task.FromResult(serializer.Deserialize(stream, null)); } } public async Task ReadBlobAsync(string name, Func handler) { Guard.NotNullOrEmpty(name, nameof(name)); Guard.NotNull(handler, nameof(handler)); var entry = GetEntry(name); using (var stream = entry.Open()) { await handler(stream); } } private ZipArchiveEntry GetEntry(string name) { var attachmentEntry = archive.GetEntry(ArchiveHelper.GetAttachmentPath(name)); if (attachmentEntry == null || attachmentEntry.Length == 0) { throw new FileNotFoundException("Cannot find attachment.", name); } readAttachments++; return attachmentEntry; } public async Task ReadEventsAsync(IStreamNameResolver streamNameResolver, IEventDataFormatter formatter, Func<(string Stream, Envelope Event), Task> handler) { Guard.NotNull(handler, nameof(handler)); Guard.NotNull(formatter, nameof(formatter)); Guard.NotNull(streamNameResolver, nameof(streamNameResolver)); while (true) { var eventEntry = archive.GetEntry(ArchiveHelper.GetEventPath(readEvents)); if (eventEntry == null) { break; } using (var stream = eventEntry.Open()) { var storedEvent = serializer.Deserialize(stream).ToStoredEvent(); var eventStream = storedEvent.StreamName; var eventEnvelope = formatter.Parse(storedEvent); await handler((eventStream, eventEnvelope)); } readEvents++; } } } }