Backup step: reporting on a committed snapshot cannot fail the run; check the snapshot row after a unique violation

This commit is contained in:
2026-10-11 12:30:05 +02:00
parent 6385925845
commit 8e273ac259
+12 -1
View File
@@ -168,6 +168,9 @@ final class BackupService {
} }
if ($state['files']['phase'] === 'done') { if ($state['files']['phase'] === 'done') {
$this->recordSnapshot($run, $state['files']); $this->recordSnapshot($run, $state['files']);
// The snapshot is committed: what follows only reports on it and must not turn
// the run into a failure.
try {
$this->alerts->storedBytes($target, $repo->storedBytes()); $this->alerts->storedBytes($target, $repo->storedBytes());
$stats = $state['files']['stats']; $stats = $state['files']['stats'];
if (($stats['unreadable'] ?? 0) > 0 || ($stats['changing'] ?? 0) > 0) { if (($stats['unreadable'] ?? 0) > 0 || ($stats['changing'] ?? 0) > 0) {
@@ -177,6 +180,9 @@ final class BackupService {
$stats['changing'] ?? 0, implode(', ', $warnings['changing']))); $stats['changing'] ?? 0, implode(', ', $warnings['changing'])));
$this->alerts->runWarnings($run, $target->getName(), (int)($stats['unreadable'] ?? 0), (int)($stats['changing'] ?? 0), $warnings); $this->alerts->runWarnings($run, $target->getName(), (int)($stats['unreadable'] ?? 0), (int)($stats['changing'] ?? 0), $warnings);
} }
} catch (\Throwable $e) {
$this->logger->warning('NG Backup run ' . $run->getId() . ': reporting on the finished backup failed: ' . $e->getMessage(), ['exception' => $e]);
}
$run->setStatus(Run::DONE); $run->setStatus(Run::DONE);
$run->setPhase('done'); $run->setPhase('done');
$run->setFinishedAt(time()); $run->setFinishedAt(time());
@@ -258,10 +264,15 @@ final class BackupService {
try { try {
$this->snapshots->insert($s); $this->snapshots->insert($s);
} catch (\OCP\DB\Exception $e) { } catch (\OCP\DB\Exception $e) {
// Recorded by another process between the check above and this insert. // Recorded by another process between the check above and this insert?
if ($e->getReason() !== \OCP\DB\Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) { if ($e->getReason() !== \OCP\DB\Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
throw $e; throw $e;
} }
try {
$this->snapshots->findOne($run->getTargetId(), $files['snapshot']);
} catch (DoesNotExistException) {
throw $e;
}
} }
} }