From 1ee41ea01c8b164e17f24b5207d5fd1401c4460a Mon Sep 17 00:00:00 2001 From: Juster Zhu Date: Sat, 2 Dec 2023 23:52:38 +0800 Subject: [PATCH] Add the backup function in the system service --- .../Domain/PO/TestamentPO.cs | 27 ---- .../Domain/PO/WillMessagePO.cs} | 28 +++- src/c#/GeneralUpdate.Core/Utils/FileUtil.cs | 6 + .../WillMessage/WillMessageManager.cs | 123 ++++++++++++++++++ .../DifferentialCore.cs | 104 --------------- .../Domain/PO/.gitkeep | 0 .../GeneralUpdate.Differential.csproj | 5 + .../WillMessage/.gitkeep | 0 .../ContentProvider/.gitkeep | 0 .../Domain/PO/.gitkeep | 0 .../GeneralUpdate.SystemService.csproj | 12 ++ .../PersistenceObjects/ProcessPersistence.cs | 11 -- .../Services/WillMessageService.cs | 39 +++++- .../Utils/.gitkeep | 0 14 files changed, 201 insertions(+), 154 deletions(-) delete mode 100644 src/c#/GeneralUpdate.Core/Domain/PO/TestamentPO.cs rename src/c#/{GeneralUpdate.SystemService/PersistenceObjects/WillMessagePersistence.cs => GeneralUpdate.Core/Domain/PO/WillMessagePO.cs} (38%) create mode 100644 src/c#/GeneralUpdate.Core/WillMessage/WillMessageManager.cs create mode 100644 src/c#/GeneralUpdate.Differential/Domain/PO/.gitkeep create mode 100644 src/c#/GeneralUpdate.Differential/WillMessage/.gitkeep create mode 100644 src/c#/GeneralUpdate.SystemService/ContentProvider/.gitkeep create mode 100644 src/c#/GeneralUpdate.SystemService/Domain/PO/.gitkeep delete mode 100644 src/c#/GeneralUpdate.SystemService/PersistenceObjects/ProcessPersistence.cs create mode 100644 src/c#/GeneralUpdate.SystemService/Utils/.gitkeep diff --git a/src/c#/GeneralUpdate.Core/Domain/PO/TestamentPO.cs b/src/c#/GeneralUpdate.Core/Domain/PO/TestamentPO.cs deleted file mode 100644 index 42de03c..0000000 --- a/src/c#/GeneralUpdate.Core/Domain/PO/TestamentPO.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; - -namespace GeneralUpdate.Core.Domain.PO -{ - public class TestamentPO - { - /// - /// The tracking id of this update request - /// - public string TrackID { get; set; } - - /// - /// dump files everywhere after an exception occurs. - /// - public string DumpPath { get; set; } - - /// - /// Backup the file path that needs to be updated before updating. - /// - public string BackupPath { get; set; } - - /// - /// Exception information that occurs when updating fails. - /// - public Exception Exception { get; set; } - } -} diff --git a/src/c#/GeneralUpdate.SystemService/PersistenceObjects/WillMessagePersistence.cs b/src/c#/GeneralUpdate.Core/Domain/PO/WillMessagePO.cs similarity index 38% rename from src/c#/GeneralUpdate.SystemService/PersistenceObjects/WillMessagePersistence.cs rename to src/c#/GeneralUpdate.Core/Domain/PO/WillMessagePO.cs index 975f65e..c714325 100644 --- a/src/c#/GeneralUpdate.SystemService/PersistenceObjects/WillMessagePersistence.cs +++ b/src/c#/GeneralUpdate.Core/Domain/PO/WillMessagePO.cs @@ -1,6 +1,9 @@ -namespace GeneralUpdate.SystemService.PersistenceObjects +using System; +using System.Collections.Generic; + +namespace GeneralUpdate.Core.Domain.PO { - internal enum ProcessStatus + internal enum WillMessageStatus { /// /// Processing has not yet begun. @@ -16,12 +19,27 @@ Failed } - internal class WillMessagePersistence where T : class + internal class BackupPO { - public List Messages { get; set; } + public string Name { get; set; } + + public string InstallPath { get; set; } + + public string BackupPath { get; set; } + + public string Version { get; set; } + + public int AppType { get; set; } + } + + internal class WillMessagePO + { + public Stack> Message { get; set; } + + public WillMessageStatus Status { get; set; } public DateTime CreateTime { get; set; } - public ProcessStatus Status { get; set; } + public DateTime ChangeTime { get; set; } } } diff --git a/src/c#/GeneralUpdate.Core/Utils/FileUtil.cs b/src/c#/GeneralUpdate.Core/Utils/FileUtil.cs index ca431c3..32d4c09 100644 --- a/src/c#/GeneralUpdate.Core/Utils/FileUtil.cs +++ b/src/c#/GeneralUpdate.Core/Utils/FileUtil.cs @@ -106,6 +106,7 @@ namespace GeneralUpdate.Core.Utils public static void CreateJsonFile(string targetPath,string fileName,T obj) { + if (!Directory.Exists(targetPath)) Directory.CreateDirectory(targetPath); var fileFullPath = Path.Combine(targetPath,fileName); if (File.Exists(fileFullPath)) File.Delete(fileFullPath); var jsonString = JsonConvert.SerializeObject(obj); @@ -124,6 +125,11 @@ namespace GeneralUpdate.Core.Utils } return default(T); } + + public static void DeleteFile(string path) + { + if (File.Exists(path)) File.Delete(path); + } } /// diff --git a/src/c#/GeneralUpdate.Core/WillMessage/WillMessageManager.cs b/src/c#/GeneralUpdate.Core/WillMessage/WillMessageManager.cs new file mode 100644 index 0000000..102d432 --- /dev/null +++ b/src/c#/GeneralUpdate.Core/WillMessage/WillMessageManager.cs @@ -0,0 +1,123 @@ +using GeneralUpdate.Core.Domain.PO; +using GeneralUpdate.Core.Utils; +using GeneralUpdate.Differential.ContentProvider; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace GeneralUpdate.Core.WillMessage +{ + internal class WillMessageManager + { + #region Private Members + + internal const string DEFULT_WILL_MESSAGE_DIR = @"C:\generalupdate_willmessages"; + internal const string DEFULT_WILL_MESSAGE_FILE = "will_message.json"; + internal const string BACKUP_ROOT_PATH = @"C:\generalupdate_backup"; + + private string _willMessageFile; + private WillMessagePO _willMessage; + private static WillMessageManager _instance; + private readonly static object _instanceLock = new object(); + + #endregion + + #region Constructors + + private WillMessageManager() { } + + #endregion + + #region Public Properties + + internal static WillMessageManager Instance + { + get + { + if (_instance == null) + { + lock (_instanceLock) + { + if (_instance == null) + { + _instance = new WillMessageManager(); + } + } + } + return _instance; + } + } + + #endregion + + #region Public Methods + + internal WillMessagePO GetWillMessage(string path = null) + { + _willMessageFile = string.IsNullOrWhiteSpace(path) ? GetFilePath() : path; + return _willMessage = FileUtil.ReadJsonFile(_willMessageFile); + } + + internal void Clear() + { + FileUtil.DeleteFile(_willMessageFile); + _willMessage = null; + DeleteRootDir(); + } + + internal async Task> Backup(string appPath, string packetPath, string version,int appType) + { + if (!Directory.Exists(BACKUP_ROOT_PATH)) + Directory.CreateDirectory(BACKUP_ROOT_PATH); + + var versionDir = Path.Combine(BACKUP_ROOT_PATH, version); + if (!Directory.Exists(versionDir)) + Directory.CreateDirectory(versionDir); + + //Take the left tree as the center to match the files that are not in the right tree . + var fileProvider = new FileProvider(); + var nodes = await fileProvider.Compare(appPath, packetPath); + var backups = new List(); + foreach (var node in nodes.Item3) + { + backups.Add(new BackupPO { Name = node.Name , Version = version , AppType = appType, InstallPath = node.Path , BackupPath = versionDir }); + } + return backups; + } + + private void BuilderWillMessage() + { + _willMessage = new WillMessagePO(); + _willMessage.ChangeTime = DateTime.Now; + _willMessage.CreateTime = DateTime.Now; + _willMessage.Status = WillMessageStatus.NotStarted; + } + + #endregion + + #region Private Methods + + private string GetFilePath() => Path.Combine(DEFULT_WILL_MESSAGE_DIR, $"{DateTime.Now.ToString("yyyyMMdd")}_{DEFULT_WILL_MESSAGE_FILE}"); + + private void Create(WillMessagePO willMessage) + { + if (willMessage == null) return; + _willMessage = willMessage; + FileUtil.CreateJsonFile(DEFULT_WILL_MESSAGE_DIR, $"{DateTime.Now.ToString("yyyyMMdd")}_{DEFULT_WILL_MESSAGE_FILE}", willMessage); + } + + /// + /// Delete the backup file directory and recursively delete all backup content. + /// + private void DeleteRootDir() + { + if (string.IsNullOrWhiteSpace(BACKUP_ROOT_PATH)) return; + if (Directory.Exists(BACKUP_ROOT_PATH)) + Directory.Delete(BACKUP_ROOT_PATH, true); + } + + #endregion + } +} diff --git a/src/c#/GeneralUpdate.Differential/DifferentialCore.cs b/src/c#/GeneralUpdate.Differential/DifferentialCore.cs index 9cd9d36..1b8d13a 100644 --- a/src/c#/GeneralUpdate.Differential/DifferentialCore.cs +++ b/src/c#/GeneralUpdate.Differential/DifferentialCore.cs @@ -21,8 +21,6 @@ namespace GeneralUpdate.Differential private static readonly object _lockObj = new object(); private static DifferentialCore _instance; - private Stack> _backupFiles = null; - private string _backupRootDir; /// /// Differential file format . @@ -43,16 +41,6 @@ namespace GeneralUpdate.Differential #endregion Private Members - #region Constructors - - private DifferentialCore() - { - _backupFiles = new Stack>(); - CreateRootDirInTemp(); - } - - #endregion Constructors - #region Public Properties public static DifferentialCore Instance @@ -209,74 +197,6 @@ namespace GeneralUpdate.Differential /// A collection of blacklist file name extensions that are skipped on update. public void SetBlocklist(List blackFiles, List blackFileFormats) => Filefilter.SetBlacklist(blackFiles, blackFileFormats); - /// - /// Back up the corresponding local collection of files in the update package. - /// - /// - /// - public void Backup(string appPath, string patchPath) - { - var destinationPath = CreateSubfolderInRootDir(); - var files = new List(); - foreach (string filePath in Directory.GetFiles(patchPath, "*.*", SearchOption.AllDirectories)) - { - string correspondingPathInA = filePath.Replace(patchPath, appPath); - - if (File.Exists(correspondingPathInA)) - { - string correspondingPathInC = filePath.Replace(patchPath, destinationPath); - - string directoryName = Path.GetDirectoryName(correspondingPathInC); - if (!Directory.Exists(directoryName)) - { - Directory.CreateDirectory(directoryName); - } - files.Add(correspondingPathInA); - File.Copy(correspondingPathInA, correspondingPathInC, true); - } - } - _backupFiles?.Push(files); - } - - /// - /// Delete the backup file directory and recursively delete all backup content. - /// - public void DeleteRootDir() - { - if (string.IsNullOrWhiteSpace(_backupRootDir)) return; - - if (Directory.Exists(_backupRootDir)) - Directory.Delete(_backupRootDir, true); - } - - /// - /// Restore the backup files of each version to the original directory. - /// - /// - /// - public bool Restore(string targetDirectory) - { - try - { - while (_backupFiles?.Count > 0) - { - List currentList = _backupFiles.Pop(); - foreach (var filePath in currentList) - { - string fileName = Path.GetFileName(filePath); - string destFile = Path.Combine(targetDirectory, fileName); - File.Copy(filePath, destFile, true); - } - } - return true; - } - catch (Exception) - { - return false; - } - } - - #endregion Public Methods #region Private Methods @@ -333,30 +253,6 @@ namespace GeneralUpdate.Differential private void OnCompressProgress(object sender, BaseCompressProgressEventArgs e) => _compressProgressCallback(sender, e); - /// - /// Create a root directory for backup files - /// - private void CreateRootDirInTemp() - { - if (!string.IsNullOrEmpty(_backupRootDir)) return; - string tempPath = Path.GetTempPath(); - string uniqueFolderName = Guid.NewGuid().ToString(); - _backupRootDir = Path.Combine(tempPath, uniqueFolderName); - if (!Directory.Exists(_backupRootDir)) Directory.CreateDirectory(_backupRootDir); - } - - /// - /// Create a subfolder based on the root directory of the backup file for version-by-version backup. - /// - /// - private string CreateSubfolderInRootDir() - { - string subFolderName = DateTime.Now.ToString("yyyyMMddHHmmssffff"); - string subFolderPath = Path.Combine(_backupRootDir, subFolderName); - if (!Directory.Exists(subFolderPath)) Directory.CreateDirectory(subFolderPath); - return subFolderPath; - } - #endregion Private Methods } } \ No newline at end of file diff --git a/src/c#/GeneralUpdate.Differential/Domain/PO/.gitkeep b/src/c#/GeneralUpdate.Differential/Domain/PO/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/c#/GeneralUpdate.Differential/GeneralUpdate.Differential.csproj b/src/c#/GeneralUpdate.Differential/GeneralUpdate.Differential.csproj index 3b3de6b..f9a76f9 100644 --- a/src/c#/GeneralUpdate.Differential/GeneralUpdate.Differential.csproj +++ b/src/c#/GeneralUpdate.Differential/GeneralUpdate.Differential.csproj @@ -15,18 +15,22 @@ + + + + @@ -43,6 +47,7 @@ + diff --git a/src/c#/GeneralUpdate.Differential/WillMessage/.gitkeep b/src/c#/GeneralUpdate.Differential/WillMessage/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/c#/GeneralUpdate.SystemService/ContentProvider/.gitkeep b/src/c#/GeneralUpdate.SystemService/ContentProvider/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/c#/GeneralUpdate.SystemService/Domain/PO/.gitkeep b/src/c#/GeneralUpdate.SystemService/Domain/PO/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/c#/GeneralUpdate.SystemService/GeneralUpdate.SystemService.csproj b/src/c#/GeneralUpdate.SystemService/GeneralUpdate.SystemService.csproj index b71655e..1e762ad 100644 --- a/src/c#/GeneralUpdate.SystemService/GeneralUpdate.SystemService.csproj +++ b/src/c#/GeneralUpdate.SystemService/GeneralUpdate.SystemService.csproj @@ -7,8 +7,20 @@ dotnet-GeneralUpdate.SystemService-bedd09fc-af1b-4a6f-ab25-948dc94428ae + + + + + + + + + + + + diff --git a/src/c#/GeneralUpdate.SystemService/PersistenceObjects/ProcessPersistence.cs b/src/c#/GeneralUpdate.SystemService/PersistenceObjects/ProcessPersistence.cs deleted file mode 100644 index bb4dd8d..0000000 --- a/src/c#/GeneralUpdate.SystemService/PersistenceObjects/ProcessPersistence.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace GeneralUpdate.SystemService.PersistenceObjects -{ - internal class ProcessPersistence - { - public string Name { get; set; } - - public string Path { get; set; } - - public string BackupPath { get; set; } - } -} diff --git a/src/c#/GeneralUpdate.SystemService/Services/WillMessageService.cs b/src/c#/GeneralUpdate.SystemService/Services/WillMessageService.cs index d4408e9..64bebd9 100644 --- a/src/c#/GeneralUpdate.SystemService/Services/WillMessageService.cs +++ b/src/c#/GeneralUpdate.SystemService/Services/WillMessageService.cs @@ -1,14 +1,28 @@ -using GeneralUpdate.SystemService.PersistenceObjects; +using GeneralUpdate.Core.Domain.PO; +using GeneralUpdate.Core.WillMessage; namespace GeneralUpdate.SystemService.Services { internal class WillMessageService : BackgroundService { + #region Private Members + private readonly string? _path; private FileSystemWatcher _fileWatcher; + #endregion + + #region Constructors + public WillMessageService(IConfiguration configuration) => _path = configuration.GetValue("WatcherPath"); + #endregion + + #region Public Properties + #endregion + + #region Public Methods + protected override Task ExecuteAsync(CancellationToken stoppingToken) { stoppingToken.Register(() => OnStopping()); @@ -22,24 +36,35 @@ namespace GeneralUpdate.SystemService.Services return Task.CompletedTask; } + #endregion + + #region Private Methods + private void OnChanged(object sender, FileSystemEventArgs e) { - var willMessage = new WillMessagePersistence(); - switch (willMessage.Status) + var message = WillMessageManager.Instance.GetWillMessage(); + if (message == null) return; + switch (message.Status) { - case ProcessStatus.NotStarted: - break; - case ProcessStatus.Failed: + case WillMessageStatus.NotStarted: + return; + case WillMessageStatus.Failed: + //WillMessageManager.Instance.Restore(); break; - case ProcessStatus.Completed: + case WillMessageStatus.Completed: + WillMessageManager.Instance.Clear(); break; } } private void OnStopping() { + if (_fileWatcher == null) return; _fileWatcher.EnableRaisingEvents = false; _fileWatcher.Dispose(); } + + + #endregion } } diff --git a/src/c#/GeneralUpdate.SystemService/Utils/.gitkeep b/src/c#/GeneralUpdate.SystemService/Utils/.gitkeep new file mode 100644 index 0000000..e69de29 -- Gitee