mirror of https://github.com/Squidex/squidex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
5.6 KiB
162 lines
5.6 KiB
// ==========================================================================
|
|
// Squidex Headless CMS
|
|
// ==========================================================================
|
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|
// All rights reserved. Licensed under the MIT license.
|
|
// ==========================================================================
|
|
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Threading.Tasks;
|
|
using Squidex.Domain.Apps.Core.Tags;
|
|
using Squidex.Domain.Apps.Entities.Assets.State;
|
|
using Squidex.Domain.Apps.Entities.Backup;
|
|
using Squidex.Domain.Apps.Events.Assets;
|
|
using Squidex.Infrastructure;
|
|
using Squidex.Infrastructure.Assets;
|
|
using Squidex.Infrastructure.Commands;
|
|
using Squidex.Infrastructure.EventSourcing;
|
|
|
|
namespace Squidex.Domain.Apps.Entities.Assets
|
|
{
|
|
public sealed class BackupAssets : IBackupHandler
|
|
{
|
|
private const string TagsFile = "AssetTags.json";
|
|
private readonly HashSet<DomainId> assetIds = new HashSet<DomainId>();
|
|
private readonly HashSet<DomainId> assetFolderIds = new HashSet<DomainId>();
|
|
private readonly Rebuilder rebuilder;
|
|
private readonly IAssetFileStore assetFileStore;
|
|
private readonly ITagService tagService;
|
|
|
|
public string Name { get; } = "Assets";
|
|
|
|
public BackupAssets(Rebuilder rebuilder, IAssetFileStore assetFileStore, ITagService tagService)
|
|
{
|
|
Guard.NotNull(rebuilder, nameof(rebuilder));
|
|
Guard.NotNull(assetFileStore, nameof(assetFileStore));
|
|
Guard.NotNull(tagService, nameof(tagService));
|
|
|
|
this.rebuilder = rebuilder;
|
|
this.assetFileStore = assetFileStore;
|
|
this.tagService = tagService;
|
|
}
|
|
|
|
public Task BackupAsync(BackupContext context)
|
|
{
|
|
return BackupTagsAsync(context);
|
|
}
|
|
|
|
public Task BackupEventAsync(Envelope<IEvent> @event, BackupContext context)
|
|
{
|
|
switch (@event.Payload)
|
|
{
|
|
case AssetCreated assetCreated:
|
|
return WriteAssetAsync(
|
|
assetCreated.AppId.Id,
|
|
assetCreated.AssetId,
|
|
assetCreated.FileVersion,
|
|
context.Writer);
|
|
case AssetUpdated assetUpdated:
|
|
return WriteAssetAsync(
|
|
assetUpdated.AppId.Id,
|
|
assetUpdated.AssetId,
|
|
assetUpdated.FileVersion,
|
|
context.Writer);
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public async Task<bool> RestoreEventAsync(Envelope<IEvent> @event, RestoreContext context)
|
|
{
|
|
switch (@event.Payload)
|
|
{
|
|
case AssetFolderCreated _:
|
|
assetFolderIds.Add(@event.Headers.AggregateId());
|
|
break;
|
|
case AssetCreated assetCreated:
|
|
assetIds.Add(@event.Headers.AggregateId());
|
|
|
|
await ReadAssetAsync(
|
|
assetCreated.AppId.Id,
|
|
assetCreated.AssetId,
|
|
assetCreated.FileVersion,
|
|
context.Reader);
|
|
break;
|
|
case AssetUpdated assetUpdated:
|
|
await ReadAssetAsync(
|
|
assetUpdated.AppId.Id,
|
|
assetUpdated.AssetId,
|
|
assetUpdated.FileVersion,
|
|
context.Reader);
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public async Task RestoreAsync(RestoreContext context)
|
|
{
|
|
await RestoreTagsAsync(context);
|
|
|
|
if (assetIds.Count > 0)
|
|
{
|
|
await rebuilder.InsertManyAsync<AssetDomainObject, AssetState>(assetIds);
|
|
}
|
|
|
|
if (assetFolderIds.Count > 0)
|
|
{
|
|
await rebuilder.InsertManyAsync<AssetFolderDomainObject, AssetFolderState>(assetFolderIds);
|
|
}
|
|
}
|
|
|
|
private async Task RestoreTagsAsync(RestoreContext context)
|
|
{
|
|
var tags = await context.Reader.ReadJsonAsync<TagsExport>(TagsFile);
|
|
|
|
await tagService.RebuildTagsAsync(context.AppId, TagGroups.Assets, tags);
|
|
}
|
|
|
|
private async Task BackupTagsAsync(BackupContext context)
|
|
{
|
|
var tags = await tagService.GetExportableTagsAsync(context.AppId, TagGroups.Assets);
|
|
|
|
await context.Writer.WriteJsonAsync(TagsFile, tags);
|
|
}
|
|
|
|
private async Task WriteAssetAsync(DomainId appId, DomainId assetId, long fileVersion, IBackupWriter writer)
|
|
{
|
|
try
|
|
{
|
|
await writer.WriteBlobAsync(GetName(assetId, fileVersion), stream =>
|
|
{
|
|
return assetFileStore.DownloadAsync(appId, assetId, fileVersion, stream);
|
|
});
|
|
}
|
|
catch (AssetNotFoundException)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
private async Task ReadAssetAsync(DomainId appId, DomainId assetId, long fileVersion, IBackupReader reader)
|
|
{
|
|
try
|
|
{
|
|
await reader.ReadBlobAsync(GetName(assetId, fileVersion), stream =>
|
|
{
|
|
return assetFileStore.UploadAsync(appId, assetId, fileVersion, stream);
|
|
});
|
|
}
|
|
catch (FileNotFoundException)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
private static string GetName(DomainId assetId, long fileVersion)
|
|
{
|
|
return $"{assetId}_{fileVersion}.asset";
|
|
}
|
|
}
|
|
}
|
|
|