ardabeyazoglu/php-retention

文件保留策略计算

v1.0.4 2024-02-06 12:54 UTC

This package is auto-updated.

Last update: 2024-09-16 13:54:02 UTC


README

build codecov

这是一个简单但实用的PHP库,可以在删除、归档或执行自定义回调操作之前应用文件保留策略。一个典型的例子是根据自定义策略(例如“保留最后7天的每日、2周的每周和3个月的备份”)进行备份归档。

特性

  • 应用每小时、每天、每周、每月和每年的策略
  • 自定义修剪操作,执行除删除之外的其他操作(例如,将它们移动到云端)
  • 自定义文件查找逻辑(例如,支持不同的存储接口,如S3)
  • 分组文件(例如,一次性修剪多个文件而不是单个文件)
  • 可运行干运行
  • 了解日志器
  • 无依赖

安装

composer require ardabeyazoglu/php-retention

测试

composer test

使用

// define retention policy (UTC timezone)
$retention = new PhpRetention\Retention([
    "keep-daily" => 7,
    "keep-weekly" => 4,
    "keep-monthly" => 6,
    "keep-yearly" => 2
]);

// customize finder logic if required
$retention->setFindHandler(function () {});

// customize time calculation if required
$retention->setTimeHandler(function () {});

// customize time calculation if required
$retention->setPruneHandler(function () {});

// apply retention in given directory (this WILL PRUNE the files!)
$result = $retention->apply("/path/to/files");
print_r($result);

策略配置

此库受Restic的策略模型的启发。如果不了解其工作原理,策略配置可能会引起误导。请阅读说明以了解每个keep-***参数的工作方式。

keep-last: keep the most recent N files. (default: 1)
keep-hourly: for the last N hours which have one or more files, keep only the most recent one for each hour.
keep-daily: for the last N days which have one or more files, keep only the most recent one for each day.
keep-weekly: for the last N weeks which have one or more files, keep only the most recent one for each week.
keep-monthly: for the last N months which have one or more files, keep only the most recent one for each month.
keep-yearly: for the last N years which have one or more files, keep only the most recent one for each year.

示例

1. 自定义查找器

默认情况下,它将递归地扫描目标目录并应用保留策略到目标目录中的每个文件或目录。这对于本地文件、挂载分区以及使用外部存储协议的流包装器等情况是合适的。在其他所有情况下,必须实现自定义查找器逻辑来检测应用保留策略的文件。

// get list of files from ftp
$rets->setFindHandler(function (string $targetDir) use ($ftpConnection) {
    $files = [];
    $fileList = ftp_mlsd($ftpConnection, $targetDir) ?: [];
    foreach ($fileList as $file) {
        $filename = $file['name'];
        $time = (int) $file['modify'];

        if (preg_match('/^backup_\w+\.zip$/', $filename)) {
            $date = new DateTimeImmutable('now', new DateTimeZone('UTC'));
            $date = $date->setTimestamp($time);

            $filepath = "$targetDir/$filename";

            $files[] = new FileInfo(
                date: $date,
                path: $filepath,
                isDirectory: false
            );
        }
    }

    return $files;
});

2. 自定义时间解析器

默认情况下,它将检查文件的posix修改时间以检测日期和时间信息。可以使用自定义函数来覆盖它,以解析不同的日期值。对于从自定义文件名格式中读取日期信息非常有用。

注意:这仅在默认查找器逻辑中使用。如果您正在编写自己的findHandler,该函数负责提供具有有效日期信息的有效文件列表。

// assume the files waiting for retention have this format: "backup@YYYYmmdd.zip"
$ret->setTimeHandler(function (string $filepath, bool $isDirectory) {
    if (preg_match('/^backup@([0-9]{4})([0-9]{2})([0-9]{2})\.zip$/', basename($filepath), $matches)) {
        $year = intval($matches[1]);
        $month = intval($matches[2]);
        $day = intval($matches[3]);

        $date = new DateTimeImmutable('now', new DateTimeZone('UTC'));
        $date = $date->setDate($year, $month, $day)->setTime(0, 0, 0, 0);

        return new FileInfo(
            date: $date,
            path: $filepath,
            isDirectory: $isDirectory
        );
    }
    else {
        return null;
    }
});

3. 自定义修剪操作

默认的修剪操作是文件的unlink和空目录的rmdir。它可以自定义为调用不同的删除函数或执行除删除之外的其他操作。

$ret->setPruneHandler(function (FileInfo $fileInfo) use ($ftpConnection) {
    ftp_delete($ftpConnection, $fileInfo->path);
});

一起修剪的文件分组

假设目录包含多个针对同一日期但不同目的的备份文件。可以使用正则表达式对它们进行分组以应用相同的保留策略。

# example:
/backup/tenant/mysql-20240106.tar.gz
/backup/tenant/files-20240106.tar.gz
/backup/tenant/mysql-20240107.tar.gz
/backup/tenant/files-20240107.tar.gz

如果没有以下函数,"keep-last=1"策略将仅修剪第一个文件。通过根据日期分组,它将一起修剪前两个文件。

// group different types of backups based on tenant and date and prune them together
$ret->setGroupHandler(function (string $filepath) { 
    if (preg_match('/\-([0-9]{8})\.tar\.gz$/', $filepath, $matches)) {
        // group by date str
        return $matches[1];
    }

    return null;
});

贡献

如果您遇到错误或想要实现新功能,请随意提交问题。请确保您的帖子描述详细。

待办事项

  • 添加keep-within-***策略支持