From 2cbcd8b63bcd7e3d45cd92baa5bacd828527aea8 Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 27 Apr 2021 18:38:26 +0800 Subject: refactor: Refactor is still on... --- BackEnd/Timeline/Services/Data/DataManager.cs | 6 +- .../Services/Data/DataManagerExtensions.cs | 5 +- .../DataServicesServiceCollectionExtensions.cs | 15 +++ BackEnd/Timeline/Services/Data/IDataManager.cs | 6 +- .../DatabaseManagement/DatabaseBackupService.cs | 11 +- .../DatabaseManagement/DatabaseCustomMigrator.cs | 17 +-- .../DatabaseManagement/IDatabaseBackupService.cs | 10 ++ .../DatabaseManagement/IDatabaseCustomMigration.cs | 9 ++ .../DatabaseManagement/IDatabaseCustomMigrator.cs | 10 ++ .../MigationServiceCollectionExtensions.cs | 9 +- .../DatabaseManagement/Resource.Designer.cs | 108 +++++++++++++++++ .../Services/DatabaseManagement/Resource.resx | 135 +++++++++++++++++++++ .../TimelinePostContentToDataMigration.cs | 4 +- .../Services/Timeline/TimelinePostService.cs | 4 +- .../Timeline/Services/User/UserAvatarService.cs | 6 +- BackEnd/Timeline/Timeline.csproj | 9 ++ 16 files changed, 329 insertions(+), 35 deletions(-) create mode 100644 BackEnd/Timeline/Services/Data/DataServicesServiceCollectionExtensions.cs create mode 100644 BackEnd/Timeline/Services/DatabaseManagement/IDatabaseBackupService.cs create mode 100644 BackEnd/Timeline/Services/DatabaseManagement/IDatabaseCustomMigrator.cs create mode 100644 BackEnd/Timeline/Services/DatabaseManagement/Resource.Designer.cs create mode 100644 BackEnd/Timeline/Services/DatabaseManagement/Resource.resx diff --git a/BackEnd/Timeline/Services/Data/DataManager.cs b/BackEnd/Timeline/Services/Data/DataManager.cs index 9de17da3..6cf3225f 100644 --- a/BackEnd/Timeline/Services/Data/DataManager.cs +++ b/BackEnd/Timeline/Services/Data/DataManager.cs @@ -21,7 +21,7 @@ namespace Timeline.Services.Data _eTagGenerator = eTagGenerator; } - public async Task RetainEntry(byte[] data, CancellationToken cancellationToken = default) + public async Task RetainEntryAsync(byte[] data, CancellationToken cancellationToken = default) { if (data == null) throw new ArgumentNullException(nameof(data)); @@ -56,7 +56,7 @@ namespace Timeline.Services.Data return tag; } - public async Task FreeEntry(string tag, CancellationToken cancellationToken = default) + public async Task FreeEntryAsync(string tag, CancellationToken cancellationToken = default) { if (tag == null) throw new ArgumentNullException(nameof(tag)); @@ -87,7 +87,7 @@ namespace Timeline.Services.Data } } - public async Task GetEntry(string tag, CancellationToken cancellationToken = default) + public async Task GetEntryAsync(string tag, CancellationToken cancellationToken = default) { if (tag == null) throw new ArgumentNullException(nameof(tag)); diff --git a/BackEnd/Timeline/Services/Data/DataManagerExtensions.cs b/BackEnd/Timeline/Services/Data/DataManagerExtensions.cs index 64d35b9b..d149f3fa 100644 --- a/BackEnd/Timeline/Services/Data/DataManagerExtensions.cs +++ b/BackEnd/Timeline/Services/Data/DataManagerExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; namespace Timeline.Services.Data @@ -8,7 +9,7 @@ namespace Timeline.Services.Data /// /// Try to get an entry and throw if not exist. /// - public static async Task GetEntryAndCheck(this IDataManager dataManager, string tag, string notExistMessage) + public static async Task GetEntryAndCheck(this IDataManager dataManager, string tag, string notExistMessage, CancellationToken cancellationToken = default) { if (dataManager is null) throw new ArgumentNullException(nameof(dataManager)); @@ -17,7 +18,7 @@ namespace Timeline.Services.Data if (notExistMessage is null) throw new ArgumentNullException(nameof(notExistMessage)); - var data = await dataManager.GetEntry(tag); + var data = await dataManager.GetEntryAsync(tag, cancellationToken); if (data is null) throw new DatabaseCorruptedException(string.Format(Resource.GetEntryAndCheckNotExist, tag, notExistMessage)); return data; diff --git a/BackEnd/Timeline/Services/Data/DataServicesServiceCollectionExtensions.cs b/BackEnd/Timeline/Services/Data/DataServicesServiceCollectionExtensions.cs new file mode 100644 index 00000000..2717e63c --- /dev/null +++ b/BackEnd/Timeline/Services/Data/DataServicesServiceCollectionExtensions.cs @@ -0,0 +1,15 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Timeline.Services.Data +{ + public static class DataServicesServiceCollectionExtensions + { + public static IServiceCollection AddDataServices(this IServiceCollection services) + { + services.TryAddScoped(); + services.TryAddScoped(); + return services; + } + } +} diff --git a/BackEnd/Timeline/Services/Data/IDataManager.cs b/BackEnd/Timeline/Services/Data/IDataManager.cs index 6a87c1b2..4191367e 100644 --- a/BackEnd/Timeline/Services/Data/IDataManager.cs +++ b/BackEnd/Timeline/Services/Data/IDataManager.cs @@ -23,7 +23,7 @@ namespace Timeline.Services.Data /// Cancellation token. /// The tag of the created entry. /// Thrown when is null. - public Task RetainEntry(byte[] data, CancellationToken cancellationToken = default); + public Task RetainEntryAsync(byte[] data, CancellationToken cancellationToken = default); /// /// Decrease the the ref count of the entry. @@ -35,7 +35,7 @@ namespace Timeline.Services.Data /// /// It's no-op if entry with tag does not exist. /// - public Task FreeEntry(string tag, CancellationToken cancellationToken = default); + public Task FreeEntryAsync(string tag, CancellationToken cancellationToken = default); /// /// Retrieve the entry with given tag. If not exist, returns null. @@ -44,6 +44,6 @@ namespace Timeline.Services.Data /// Cancellation token. /// The data of the entry. If not exist, returns null. /// Thrown when is null. - public Task GetEntry(string tag, CancellationToken cancellationToken = default); + public Task GetEntryAsync(string tag, CancellationToken cancellationToken = default); } } diff --git a/BackEnd/Timeline/Services/DatabaseManagement/DatabaseBackupService.cs b/BackEnd/Timeline/Services/DatabaseManagement/DatabaseBackupService.cs index c00b5f95..718edcb1 100644 --- a/BackEnd/Timeline/Services/DatabaseManagement/DatabaseBackupService.cs +++ b/BackEnd/Timeline/Services/DatabaseManagement/DatabaseBackupService.cs @@ -1,4 +1,5 @@ using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using System.Globalization; using System.IO; using System.Threading; @@ -7,19 +8,16 @@ using Timeline.Entities; namespace Timeline.Services.DatabaseManagement { - public interface IDatabaseBackupService - { - Task BackupAsync(CancellationToken cancellationToken = default); - } - public class DatabaseBackupService : IDatabaseBackupService { + private readonly ILogger _logger; private readonly DatabaseContext _database; private readonly IPathProvider _pathProvider; private readonly IClock _clock; - public DatabaseBackupService(DatabaseContext database, IPathProvider pathProvider, IClock clock) + public DatabaseBackupService(ILogger logger, DatabaseContext database, IPathProvider pathProvider, IClock clock) { + _logger = logger; _database = database; _pathProvider = pathProvider; _clock = clock; @@ -32,6 +30,7 @@ namespace Timeline.Services.DatabaseManagement var fileName = _clock.GetCurrentTime().ToString("yyyy-MM-ddTHH-mm-ss", CultureInfo.InvariantCulture); var path = Path.Combine(backupDirPath, fileName); await _database.Database.ExecuteSqlInterpolatedAsync($"VACUUM INTO {path}", cancellationToken); + _logger.LogWarning(Resource.DatabaseBackupServiceFinishBackup, path); } } } diff --git a/BackEnd/Timeline/Services/DatabaseManagement/DatabaseCustomMigrator.cs b/BackEnd/Timeline/Services/DatabaseManagement/DatabaseCustomMigrator.cs index 2180ad40..20e2c074 100644 --- a/BackEnd/Timeline/Services/DatabaseManagement/DatabaseCustomMigrator.cs +++ b/BackEnd/Timeline/Services/DatabaseManagement/DatabaseCustomMigrator.cs @@ -7,17 +7,12 @@ using Timeline.Entities; namespace Timeline.Services.DatabaseManagement { - public interface IDatabaseCustomMigrator - { - Task MigrateAsync(CancellationToken cancellationToken = default); - } - public class DatabaseCustomMigrator : IDatabaseCustomMigrator { - private IEnumerable _migrations; - private DatabaseContext _database; + private readonly IEnumerable _migrations; + private readonly DatabaseContext _database; - private ILogger _logger; + private readonly ILogger _logger; public DatabaseCustomMigrator(IEnumerable migrations, DatabaseContext database, ILogger logger) { @@ -33,11 +28,11 @@ namespace Timeline.Services.DatabaseManagement var name = migration.GetName(); var isApplied = await _database.Migrations.AnyAsync(m => m.Name == name, cancellationToken); - _logger.LogInformation("Found custom migration '{0}'. Applied: {1}.", name, isApplied); + _logger.LogInformation(Resource.DatabaseCustomMigratorFoundMigration, name, isApplied); if (!isApplied) { - _logger.LogWarning("Begin custom migration '{0}'.", name); + _logger.LogWarning(Resource.DatabaseCustomMigratorBeginMigration, name); await using var transaction = await _database.Database.BeginTransactionAsync(cancellationToken); @@ -48,7 +43,7 @@ namespace Timeline.Services.DatabaseManagement await transaction.CommitAsync(cancellationToken); - _logger.LogWarning("End custom migration '{0}'.", name); + _logger.LogWarning(Resource.DatabaseCustomMigratorFinishMigration, name); } } } diff --git a/BackEnd/Timeline/Services/DatabaseManagement/IDatabaseBackupService.cs b/BackEnd/Timeline/Services/DatabaseManagement/IDatabaseBackupService.cs new file mode 100644 index 00000000..88f3d9b6 --- /dev/null +++ b/BackEnd/Timeline/Services/DatabaseManagement/IDatabaseBackupService.cs @@ -0,0 +1,10 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace Timeline.Services.DatabaseManagement +{ + public interface IDatabaseBackupService + { + Task BackupAsync(CancellationToken cancellationToken = default); + } +} diff --git a/BackEnd/Timeline/Services/DatabaseManagement/IDatabaseCustomMigration.cs b/BackEnd/Timeline/Services/DatabaseManagement/IDatabaseCustomMigration.cs index 7300ccbd..a38dcb99 100644 --- a/BackEnd/Timeline/Services/DatabaseManagement/IDatabaseCustomMigration.cs +++ b/BackEnd/Timeline/Services/DatabaseManagement/IDatabaseCustomMigration.cs @@ -7,6 +7,15 @@ namespace Timeline.Services.DatabaseManagement public interface IDatabaseCustomMigration { string GetName(); + + /// + /// Execute the migration on database. + /// + /// The database. + /// Cancellation token. + /// + /// Do not create transaction since the migrator will take care of transaction. + /// Task ExecuteAsync(DatabaseContext database, CancellationToken cancellationToken = default); } } diff --git a/BackEnd/Timeline/Services/DatabaseManagement/IDatabaseCustomMigrator.cs b/BackEnd/Timeline/Services/DatabaseManagement/IDatabaseCustomMigrator.cs new file mode 100644 index 00000000..5eb43b92 --- /dev/null +++ b/BackEnd/Timeline/Services/DatabaseManagement/IDatabaseCustomMigrator.cs @@ -0,0 +1,10 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace Timeline.Services.DatabaseManagement +{ + public interface IDatabaseCustomMigrator + { + Task MigrateAsync(CancellationToken cancellationToken = default); + } +} diff --git a/BackEnd/Timeline/Services/DatabaseManagement/MigationServiceCollectionExtensions.cs b/BackEnd/Timeline/Services/DatabaseManagement/MigationServiceCollectionExtensions.cs index d1f9b51c..8269ce28 100644 --- a/BackEnd/Timeline/Services/DatabaseManagement/MigationServiceCollectionExtensions.cs +++ b/BackEnd/Timeline/Services/DatabaseManagement/MigationServiceCollectionExtensions.cs @@ -1,14 +1,17 @@ using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; namespace Timeline.Services.DatabaseManagement { - public static class DatabaseManagementServiceCollectionExtensions + public static class DatabaseManagementServicesServiceCollectionExtensions { public static IServiceCollection AddDatabaseManagementService(this IServiceCollection services) { - services.AddScoped(); + services.TryAddScoped(); services.AddScoped(); - services.AddScoped(); + + services.TryAddScoped(); + services.AddHostedService(); return services; } diff --git a/BackEnd/Timeline/Services/DatabaseManagement/Resource.Designer.cs b/BackEnd/Timeline/Services/DatabaseManagement/Resource.Designer.cs new file mode 100644 index 00000000..c0e61a3f --- /dev/null +++ b/BackEnd/Timeline/Services/DatabaseManagement/Resource.Designer.cs @@ -0,0 +1,108 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Timeline.Services.DatabaseManagement { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resource { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resource() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Timeline.Services.DatabaseManagement.Resource", typeof(Resource).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Database backup finished with output file at {0}.. + /// + internal static string DatabaseBackupServiceFinishBackup { + get { + return ResourceManager.GetString("DatabaseBackupServiceFinishBackup", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Begin custom migration '{0}'.. + /// + internal static string DatabaseCustomMigratorBeginMigration { + get { + return ResourceManager.GetString("DatabaseCustomMigratorBeginMigration", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to End custom migration '{0}'.. + /// + internal static string DatabaseCustomMigratorFinishMigration { + get { + return ResourceManager.GetString("DatabaseCustomMigratorFinishMigration", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Found custom migration '{0}'. Applied: {1}.. + /// + internal static string DatabaseCustomMigratorFoundMigration { + get { + return ResourceManager.GetString("DatabaseCustomMigratorFoundMigration", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Old image content does not have corresponding data with the tag.. + /// + internal static string TimelinePostContentToDataMigrationImageNoData { + get { + return ResourceManager.GetString("TimelinePostContentToDataMigrationImageNoData", resourceCulture); + } + } + } +} diff --git a/BackEnd/Timeline/Services/DatabaseManagement/Resource.resx b/BackEnd/Timeline/Services/DatabaseManagement/Resource.resx new file mode 100644 index 00000000..9480ce64 --- /dev/null +++ b/BackEnd/Timeline/Services/DatabaseManagement/Resource.resx @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Database backup finished with output file at {0}. + + + Begin custom migration '{0}'. + + + End custom migration '{0}'. + + + Found custom migration '{0}'. Applied: {1}. + + + Old image content does not have corresponding data with the tag. + + \ No newline at end of file diff --git a/BackEnd/Timeline/Services/DatabaseManagement/TimelinePostContentToDataMigration.cs b/BackEnd/Timeline/Services/DatabaseManagement/TimelinePostContentToDataMigration.cs index f9a3418b..f6662a97 100644 --- a/BackEnd/Timeline/Services/DatabaseManagement/TimelinePostContentToDataMigration.cs +++ b/BackEnd/Timeline/Services/DatabaseManagement/TimelinePostContentToDataMigration.cs @@ -35,7 +35,7 @@ namespace Timeline.Services.DatabaseManagement { if (postEntity.ContentType == "text") { - var tag = await _dataManager.RetainEntry(Encoding.UTF8.GetBytes(postEntity.Content)); + var tag = await _dataManager.RetainEntryAsync(Encoding.UTF8.GetBytes(postEntity.Content), cancellationToken); database.TimelinePostData.Add(new TimelinePostDataEntity { DataTag = tag, @@ -47,7 +47,7 @@ namespace Timeline.Services.DatabaseManagement } else { - var data = await _dataManager.GetEntryAndCheck(postEntity.Content, "Old image content does not have corresponding data with the tag."); + var data = await _dataManager.GetEntryAndCheck(postEntity.Content, Resource.TimelinePostContentToDataMigrationImageNoData, cancellationToken); var format = Image.DetectFormat(data); database.TimelinePostData.Add(new TimelinePostDataEntity { diff --git a/BackEnd/Timeline/Services/Timeline/TimelinePostService.cs b/BackEnd/Timeline/Services/Timeline/TimelinePostService.cs index 073fffdf..6ca2e5a0 100644 --- a/BackEnd/Timeline/Services/Timeline/TimelinePostService.cs +++ b/BackEnd/Timeline/Services/Timeline/TimelinePostService.cs @@ -363,7 +363,7 @@ namespace Timeline.Services.Timeline { var data = request.DataList[index]; - var tag = await _dataManager.RetainEntry(data.Data); + var tag = await _dataManager.RetainEntryAsync(data.Data); _database.TimelinePostData.Add(new TimelinePostDataEntity { @@ -438,7 +438,7 @@ namespace Timeline.Services.Timeline foreach (var dataEntity in dataEntities) { - await _dataManager.FreeEntry(dataEntity.DataTag); + await _dataManager.FreeEntryAsync(dataEntity.DataTag); } _database.TimelinePostData.RemoveRange(dataEntities); diff --git a/BackEnd/Timeline/Services/User/UserAvatarService.cs b/BackEnd/Timeline/Services/User/UserAvatarService.cs index a92df3cb..1b8896a6 100644 --- a/BackEnd/Timeline/Services/User/UserAvatarService.cs +++ b/BackEnd/Timeline/Services/User/UserAvatarService.cs @@ -200,7 +200,7 @@ namespace Timeline.Services.User await using var transaction = await _database.Database.BeginTransactionAsync(); - var tag = await _dataManager.RetainEntry(avatar.Data); + var tag = await _dataManager.RetainEntryAsync(avatar.Data); var now = _clock.GetCurrentTime(); @@ -218,7 +218,7 @@ namespace Timeline.Services.User else { if (entity.DataTag is not null) - await _dataManager.FreeEntry(entity.DataTag); + await _dataManager.FreeEntryAsync(entity.DataTag); entity.DataTag = tag; entity.Type = avatar.ContentType; @@ -243,7 +243,7 @@ namespace Timeline.Services.User await using var transaction = await _database.Database.BeginTransactionAsync(); - await _dataManager.FreeEntry(entity.DataTag); + await _dataManager.FreeEntryAsync(entity.DataTag); entity.DataTag = null; entity.Type = null; diff --git a/BackEnd/Timeline/Timeline.csproj b/BackEnd/Timeline/Timeline.csproj index 6a74d0c0..15771977 100644 --- a/BackEnd/Timeline/Timeline.csproj +++ b/BackEnd/Timeline/Timeline.csproj @@ -143,6 +143,11 @@ True UserTokenService.resx + + True + True + Resource.resx + True True @@ -253,6 +258,10 @@ ResXFileCodeGenerator UserTokenService.Designer.cs + + ResXFileCodeGenerator + Resource.Designer.cs + ResXFileCodeGenerator Resource.Designer.cs -- cgit v1.2.3