Close remaining review gaps
- restore runs from the web are created under the location's exclusive lock, like backup runs - raw restore writes to an unpredictable temporary name opened with exclusive create (never follows a planted symlink) and validates the path prefix; the restore service rejects non-canonical paths instead of trimming them (occ normalises user input before calling it) - restore jobs report progress every minute, so a long restore is not taken for a dead one - README: Object Lock turns deletions into delete markers
This commit is contained in:
@@ -41,6 +41,23 @@ class PruneService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run $fn under the location's exclusive lock (to create a run atomically with respect to a
|
||||
* cleanup, which takes the same lock and then refuses while a run exists).
|
||||
*/
|
||||
public function underStartLock(Target $target, callable $fn): mixed {
|
||||
try {
|
||||
$this->locking->acquireLock(self::lockKey($target), ILockingProvider::LOCK_EXCLUSIVE);
|
||||
} catch (LockedException) {
|
||||
throw new \RuntimeException('A cleanup of ' . $target->getName() . ' is in progress; try again later');
|
||||
}
|
||||
try {
|
||||
return $fn();
|
||||
} finally {
|
||||
$this->locking->releaseLock(self::lockKey($target), ILockingProvider::LOCK_EXCLUSIVE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclusive lock on the location, then make sure no run of any kind (backup, restore, export)
|
||||
* is in progress: their data may not be referenced by a snapshot yet, or is being read.
|
||||
|
||||
Reference in New Issue
Block a user