Phase 0: fixes from review (torn files, pending blobs, exact sequences, UTF-8, storage checks)
- detect files changing during reading or between resumable steps and re-read them (size/mtime/ctime/inode), spike F overwrites mid-run - drop pending blob ids when a pack or index upload fails - dump and restore PostgreSQL sequence state exactly, bound parameters, validated catalog names; spike C checks all sequences exactly - keep invalid UTF-8 byte-exact (tagged base64) - refuse large tables without a primary key - StorageBackend: check write/flush/close results, validate base path - user_migration import/export: root paths, intermediate folders, partial writes, read errors - spikes: never touch an existing account, own fixtures, 512M note
This commit is contained in:
+18
-1
@@ -73,7 +73,15 @@ final class BackupRun {
|
||||
continue;
|
||||
}
|
||||
|
||||
$cur = $state['cur'] ?? ['path' => $relative, 'offset' => 0, 'blobs' => []];
|
||||
$version = Repository::fileVersion($path);
|
||||
$cur = $state['cur'];
|
||||
if ($cur === null || $cur['version'] !== $version) {
|
||||
// New file, or it changed since the previous step: (re)start reading it.
|
||||
if ($cur !== null) {
|
||||
$stats['retried'] = ($stats['retried'] ?? 0) + 1;
|
||||
}
|
||||
$cur = ['path' => $relative, 'offset' => 0, 'blobs' => [], 'version' => $version];
|
||||
}
|
||||
$fh = fopen($path, 'rb');
|
||||
fseek($fh, $cur['offset']);
|
||||
$finished = true;
|
||||
@@ -86,6 +94,15 @@ final class BackupRun {
|
||||
}
|
||||
}
|
||||
fclose($fh);
|
||||
if (Repository::fileVersion($path) !== $cur['version']) {
|
||||
// Changed while reading: start this file again (in this or the next step).
|
||||
$stats['retried'] = ($stats['retried'] ?? 0) + 1;
|
||||
$state['cur'] = null;
|
||||
if (microtime(true) >= $deadline) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!$finished) {
|
||||
$state['cur'] = $cur;
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user