网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
using Dpz.Core.Backup;
using Dpz.Core.EnumLibrary;
using Dpz.Core.Infrastructure;
using Dpz.Core.Infrastructure.Entity;
using Dpz.Core.Public.Entity;
using Dpz.Core.Public.ViewModel;
using Dpz.Core.Service.ObjectStorage.Services;
using Dpz.Core.Service.RepositoryService;
using Dpz.Core.Shard.Service;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;

namespace Dpz.Core.Web.Jobs.Hangfire;

public class BackupActivator(
    IBackupService backupService,
    IBackupRecordService backupRecordService,
    IConfiguration configuration,
    ISafeFileService safeFileService,
    ILogger<BackupActivator> logger
)
{
    public async Task BackupAsync()
    {
        var filter = new Dictionary<string, string>
        {
            {
                nameof(AccountToken),
                SerializerFilterDocument(
                    new ExpressionFilterDefinition<AccountToken>(x =>
                        x.RefreshTokenExpiryTime > DateTime.Now
                    )
                )
            },
            {
                nameof(WaitExecution),
                SerializerFilterDocument(
                    new ExpressionFilterDefinition<WaitExecution>(x =>
                        x.Status != ExecuteStatus.ExecuteComplete
                    )
                )
            },
        };

        try
        {
            await BackupMainAsync("mongodb", filter);
            await BackupMainAsync("AgileConfig");
        }
        catch (Exception e)
        {
            logger.LogError(e, "backup fail");
        }
    }

    private static string SerializerFilterDocument<T>(FilterDefinition<T> filter)
        where T : IBaseEntity
    {
        var serializerRegistry = BsonSerializer.SerializerRegistry;
        var documentSerializer = serializerRegistry.GetSerializer<T>();

        var serializerArgs = new RenderArgs<T>(documentSerializer, serializerRegistry);
        var result = filter.Render(serializerArgs);

        return result.ToString();
    }

    private async Task BackupMainAsync(
        string connectionStringName,
        Dictionary<string, string>? filter = null
    )
    {
        logger.LogInformation("Start backing up database: {Database}", connectionStringName);
        var connectionString = configuration.GetConnectionString(connectionStringName);
        backupService.UploadAsync = UploadAsync;
        var backupRecord = await backupService.BackupAsync(connectionString, filter);
        await backupRecordService.AddRecordAsync(backupRecord);
        logger.LogInformation("Database: {Database} backup complete", connectionStringName);
    }

    private async Task<VmBackupRecord?> UploadAsync(BackupResult result)
    {
        if (string.IsNullOrEmpty(result.BackupPath))
        {
            throw new BusinessException("backup path is null");
        }

        if (!File.Exists(result.BackupPath))
        {
            throw new BusinessException("backup file not exist");
        }

        var fileName = Path.GetFileName(result.BackupPath);
        var date = DateTime.Now;
        List<string> pathToFile =
        [
            "backup",
            date.Year.ToString(),
            date.Month.ToString(),
            $"{fileName}",
        ];
#if DEBUG
        pathToFile.Insert(0, "Test");
#endif
        var cloudFile = new CloudFile
        {
            PathToFile = pathToFile,
            Stream = new FileStream(
                result.BackupPath,
                FileMode.Open,
                FileAccess.Read,
                FileShare.Read,
                1 << 12
            ),
        };
        var address = await safeFileService.UploadFileForFtpAsync(cloudFile);
        if (address == null)
        {
            throw new BusinessException("upload backup file fail");
        }

        return new VmBackupRecord
        {
            Filename = string.Join('/', pathToFile),
            BackupTime = DateTime.Now,
            Database = result.Database,
            BackupPassword = result.ZipPassword,
        };
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

这段代码是一个 C# 类 BackupActivator 的实现,主要用于执行数据库备份操作。它使用了 Hangfire 进行任务调度,并依赖于多个服务来完成备份的具体工作。以下是代码的主要功能和结构的详细解释:

主要功能

  1. 备份数据库

    • BackupAsync 方法是这个类的核心方法,负责执行数据库的备份操作。它会根据特定的过滤条件备份 MongoDB 数据库和 AgileConfig 数据库。
  2. 过滤条件

    • BackupAsync 方法中,定义了一个过滤条件字典 filter,用于筛选需要备份的数据。这个过滤条件包括:
      • AccountToken:筛选 RefreshTokenExpiryTime 大于当前时间的记录。
      • WaitExecution:筛选状态不等于 ExecuteComplete 的记录。
  3. 备份主逻辑

    • BackupMainAsync 方法负责实际的备份操作。它接收数据库连接字符串的名称和可选的过滤条件,调用 backupServiceBackupAsync 方法进行备份,并记录备份记录。
  4. 序列化过滤器

    • SerializerFilterDocument 方法用于将 MongoDB 的过滤器序列化为字符串,以便在备份时使用。
  5. 上传备份文件

    • UploadAsync 方法负责将备份文件上传到安全的文件存储服务(如 FTP)。它会检查备份路径是否有效,并在上传成功后返回备份记录。
  6. 错误处理

    • BackupAsync 方法中,使用 try-catch 块来捕获可能发生的异常,并记录错误信息。

代码结构

  • 构造函数

    • BackupActivator 的构造函数接受多个依赖项,包括备份服务、备份记录服务、配置、文件服务和日志记录器。这些依赖项通过依赖注入提供。
  • 异步方法

    • 所有主要操作都是异步的,使用 asyncawait 关键字,以提高性能和响应性。
  • 条件编译

    • 使用 #if DEBUG 指令在调试模式下修改备份文件的路径,以便于测试。

总结

整体而言,BackupActivator 类实现了一个完整的数据库备份解决方案,能够根据特定条件筛选数据,执行备份,并将备份文件上传到安全存储。它利用了现代 C# 的异步编程特性和依赖注入模式,使得代码结构清晰且易于维护。

loading