Verify: retry storage exceptions only, let programming errors surface
Catch \Exception (storage adapters throw their own exception types) instead of \Throwable, so an \Error such as a TypeError is not retried and reported as an unreadable blob.
This commit is contained in:
@@ -840,7 +840,7 @@ final class Repository {
|
||||
for ($attempt = 1; $attempt <= self::VERIFY_READ_ATTEMPTS && $encrypted === null; $attempt++) {
|
||||
try {
|
||||
$encrypted = $this->backend->getRange('packs/' . substr($pack, 0, 2) . '/' . $pack, $offset, $length);
|
||||
} catch (\Throwable $e) {
|
||||
} catch (\Exception $e) { // storage adapters throw their own exceptions; \Error (a bug) is not retried
|
||||
$stats['readError'] = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,15 @@ class VerifyTest extends TestCase {
|
||||
$this->assertNotSame([], $result['unreadable']);
|
||||
$this->assertSame('connection reset', $result['readError']);
|
||||
}
|
||||
|
||||
public function testDeepVerifyDoesNotHideAProgrammingError(): void {
|
||||
$repo = Repository::initWithKey($this->backend, $this->keys, $this->keys->wrap('pw'));
|
||||
$s = $repo->backupDirectory($this->src);
|
||||
$buggy = new FlakyRangeBackend($this->backend, failures: PHP_INT_MAX, error: new \TypeError('bug'));
|
||||
|
||||
$this->expectException(\TypeError::class);
|
||||
Repository::openWithKey($buggy, $this->keys, null, null)->verify($s['snapshot'], deep: true);
|
||||
}
|
||||
}
|
||||
|
||||
/** Delegates to a real backend, but getRange() throws for the first $failures calls. */
|
||||
@@ -125,6 +134,7 @@ final class FlakyRangeBackend implements IBackend {
|
||||
public function __construct(
|
||||
private IBackend $inner,
|
||||
private int $failures,
|
||||
private ?\Throwable $error = null,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -139,7 +149,7 @@ final class FlakyRangeBackend implements IBackend {
|
||||
public function getRange(string $path, int $offset, int $length): string {
|
||||
if ($this->failures > 0) {
|
||||
$this->failures--;
|
||||
throw new BackendException('connection reset');
|
||||
throw $this->error ?? new BackendException('connection reset');
|
||||
}
|
||||
return $this->inner->getRange($path, $offset, $length);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user