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:
@@ -45,7 +45,17 @@ class RestoreJob extends QueuedJob {
|
||||
$run->setUpdatedAt(time());
|
||||
$run = $this->runs->update($run);
|
||||
@set_time_limit(0);
|
||||
$result = $this->restore->restoreUserFiles($this->targets->get((string)$run->getTargetId()), $req['snapshot'], $req['path'], $req['mode']);
|
||||
$lastBeat = time();
|
||||
$result = $this->restore->restoreUserFiles($this->targets->get((string)$run->getTargetId()), $req['snapshot'], $req['path'], $req['mode'],
|
||||
function (int $done, int $total) use (&$run, &$lastBeat): void {
|
||||
// Heartbeat, so a long restore is not mistaken for a dead one.
|
||||
if (time() - $lastBeat >= 60) {
|
||||
$lastBeat = time();
|
||||
$run->setPhase("restoring $done/$total");
|
||||
$run->setUpdatedAt(time());
|
||||
$run = $this->runs->update($run);
|
||||
}
|
||||
});
|
||||
$run->setStatus(Run::DONE);
|
||||
$run->setPhase('done');
|
||||
$run->setStats(json_encode($result, JSON_THROW_ON_ERROR));
|
||||
|
||||
Reference in New Issue
Block a user