fin/user-backup-lib
UserBackupLib
Библиотека для резервного копирования пользовательских данных из нескольких баз данных с потоковой записью, чанковым шифрованием и опциональным удалением исходных данных.
Документация:
Возможности
- Потоковое чтение данных из БД без загрузки всего набора в память.
- Потоковая запись backup JSON в файл.
- Чанковое шифрование больших backup-файлов.
- Потоковое чтение backup-файлов через
streamBackupData(). - Объектный сценарий создания backup через
UserBackupCreateOptions. - Ручной сценарий создания backup-сервиса.
- Контейнерный сценарий через factory.
- Объектный сценарий очистки через
UserDataScope. - Очистка пользовательских данных после backup.
- Keyset-пагинация (
lazyById) по числовому первичному ключу — не деградирует с глубиной; для составных/нечисловых PK автоматический OFFSET-fallback. - Подзапрос-фильтр через
FilterSubquery— заменаwhereIn([десятки тысяч литералов])на компактныйIN (SELECT ...). - Предзагрузка схемы одним запросом на подключение (таблицы/колонки/PK) — снимает per-table round-trip «налог» при обходе всех таблиц удалённой БД.
- Пустые таблицы не попадают в файл бэкапа (нечего восстанавливать) — меньше размер и быстрее restore.
Важные границы
- Пакет ориентирован в первую очередь на MySQL-подобный сценарий.
- Generic restore внутри пакета сейчас не реализован.
- Raw rows таблиц остаются массивами, потому что схема таблиц динамическая.
- Runtime-параметры backup use case не должны резолвиться напрямую из контейнера без явного scope.
Установка
composer require fin/user-backup-lib
Packagist:
Быстрый старт
Ручной сценарий
use App\Services\UserBackupService;
use App\ValueObjects\UserBackupCreateOptions;
$options = UserBackupCreateOptions::fromLegacy(
userId: 42,
accountIds: [101, 102],
activeIds: [501],
ignoredTables: ['temp_logs'],
connections: ['mysql', 'replica'],
);
$backup = UserBackupService::createFromOptions($options);
Legacy-совместимый вариант:
use App\Services\UserBackupService;
$backup = UserBackupService::create(
userId: 42,
accountIds: [101, 102],
activeIds: [501],
ignoredTables: ['temp_logs'],
connections: ['mysql', 'replica'],
);
$backup->fetchAllUserData();
$path = $backup->saveBackupToFile('/tmp/backup_42.json');
// вернется /tmp/backup_42.json.enc
Подзапрос-фильтр вместо гигантского whereIn
Когда набор значений фильтра огромен (например, десятки тысяч active_id), передача их
литеральным списком делает SQL многокилобайтным и дорогим в разборе на каждой таблице.
Вместо этого можно передать спецификацию подзапроса — библиотека подставит
active_id IN (SELECT id FROM actives WHERE user_id = ?). Подзапрос применяется только
если целевая таблица (actives) присутствует в подключении; иначе — обычный whereIn.
use App\Services\UserBackupService;
use App\ValueObjects\FilterSubquery;
$backup = UserBackupService::create(
userId: 42,
accountIds: [101, 102],
activeIds: [501, 502], // используется как fallback, если подзапрос неприменим
ignoredTables: ['temp_logs'],
connections: ['mysql', 'replica'],
activeIdSubquery: new FilterSubquery(
table: 'actives', // откуда брать id
selectColumn: 'id',
whereColumn: 'user_id',
whereValue: 42,
),
);
$backup->fetchAllUserData();
$path = $backup->saveBackupToFile('/tmp/backup_42.json');
Важно: подзапрос обязан воспроизводить тот же набор строк, что и литеральный список (те же soft-delete/scope-условия), иначе в backup попадут «лишние» строки.
Контейнерный сценарий
use App\Contracts\UserBackupServiceFactoryInterface;
use App\ValueObjects\UserDataScope;
$factory = app(UserBackupServiceFactoryInterface::class);
$backup = $factory->make(new UserDataScope(
userId: 42,
accountIds: [101, 102],
activeIds: [501],
ignoredTables: ['temp_logs'],
));
$backup->fetchAllUserData();
$path = $backup->saveBackupToFile(storage_path('app/backups/user-42.json'));
Legacy-совместимый вариант:
$backup = $factory->makeForUser(
userId: 42,
accountIds: [101, 102],
activeIds: [501],
ignoredTables: ['temp_logs'],
);
Очистка данных
use App\Contracts\UserDataDeletionServiceInterface;
use App\ValueObjects\UserDataScope;
$cleaner = app(UserDataDeletionServiceInterface::class);
$cleaner->deleteScope(new UserDataScope(
userId: 42,
accountIds: [101, 102],
activeIds: [501],
ignoredTables: ['temp_logs'],
));
Legacy-совместимый вариант:
$cleaner->deleteUserData(
userId: 42,
accountIds: [101, 102],
activeIds: [501],
ignoredTables: ['temp_logs'],
);
Чтение backup
Полная расшифровка в массив
use App\Services\FileStorageService;
$data = FileStorageService::decryptFile('/tmp/backup_42.json.enc');
Потоковое чтение
use App\Services\FileStorageService;
$storage = new FileStorageService();
foreach ($storage->streamBackupData('/tmp/backup_42.json.enc') as $entry) {
$table = $entry['table'];
$row = $entry['row'];
}
Совместимость форматов:
.jsonчитается потоково.- новый чанковый
.json.encчитается потоково. - legacy
.encподдерживается по совместимости, но не гарантирует ту же memory-efficiency на очень больших файлах.
Конфигурация
Пакетный конфиг: config/user-backup.php
return [
'connections' => ['mysql', 'replica'],
];
Правила:
- если
user-backup.connectionsпуст, пакет берет все ключи изdatabase.connections; - для шифрования используется стандартный
APP_KEYLaravel; - путь сохранения backup выбирает приложение, не пакет.
- параметр
accountIdsв текущей интеграции проекта исторический и по факту содержит ids субсчетов.
Тесты
php -d pcov.enabled=1 vendor/bin/phpunit --coverage-text --coverage-html build/coverage
Текущее покрытие пакета: 100%.
Структура
src/Contracts/*— контракты сервисов и factory.src/Services/DatabaseService.php— потоковое чтение из БД.src/Services/FileStorageService.php— запись, шифрование и чтение backup-файлов.src/Services/UserBackupService.php— orchestration backup use case.src/Services/UserBackupServiceFactory.php— factory для container-friendly сценария.src/Services/UserDataDeletionService.php— очистка данных.src/ValueObjects/*— внутренние DTO/value objects.docs/user-backup-guide.md— полная документация.
Related Packages
Powerful PHP database abstraction layer (DBAL) with many features for database s...
Laravel Serializable Closure provides an easy and secure way to serialize closur...
Cli error handling for console/command-line PHP applications.
Version History
| Version | Released | PHP | Laravel | License |
|---|---|---|---|---|
| v3.1.0 | ^8.0 | ^8.0 | MIT | |
| v3.0.0 | ^8.0 | ^8.0 | MIT | |
| v2.4.0 | ^8.0 | ^8.0 | MIT | |
| v2.3.0 | ^8.0 | ^8.0 | MIT | |
| v2.2.0 | ^8.0 | ^8.0 | MIT | |
| v2.1.0 | ^8.0 | ^8.0 | MIT | |
| v2.0.0 | ^8.0 | ^8.0 | ||
| v1.0.1 | ^8.0 | ^8.0 |