1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-19 03:50:54 +01:00

When file transforms race and lose, accept defeat gracefully

Summary: Fixes T8277. Transforming files can race; resolve the race after we lose.

Test Plan:
  - Added `sleep(10)` near the bottom of the transform controller.
  - Transformed a file in two browser windows at the same time; got something like this (exception corresponds to the loser of the race):

{F412526}

  - Applied patch.
  - Repeated process, got this:

{F412527}

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T8277

Differential Revision: https://secure.phabricator.com/D12965
This commit is contained in:
epriestley 2015-05-21 09:42:20 -07:00
parent a50de8958e
commit d70ca6b7c8

View file

@ -30,11 +30,7 @@ final class PhabricatorFileTransformController
}
$transform = $request->getURIData('transform');
$xform = id(new PhabricatorTransformedFile())
->loadOneWhere(
'originalPHID = %s AND transform = %s',
$source_phid,
$transform);
$xform = $this->loadTransform($source_phid, $transform);
if ($xform) {
if ($is_regenerate) {
@ -80,8 +76,20 @@ final class PhabricatorFileTransformController
$xform = id(new PhabricatorTransformedFile())
->setOriginalPHID($source_phid)
->setTransform($transform)
->setTransformedPHID($xformed_file->getPHID())
->save();
->setTransformedPHID($xformed_file->getPHID());
try {
$xform->save();
} catch (AphrontDuplicateKeyQueryException $ex) {
// If we collide when saving, we've raced another endpoint which was
// transforming the same file. Just throw our work away and use that
// transform instead.
$this->destroyTransform($xform);
$xform = $this->loadTransform($source_phid, $transform);
if (!$xform) {
return new Aphront404Response();
}
}
return $this->buildTransformedFileResponse($xform);
}
@ -113,7 +121,9 @@ final class PhabricatorFileTransformController
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
if (!$file) {
if ($xform->getID()) {
$xform->delete();
}
} else {
$engine->destroyObject($file);
}
@ -121,4 +131,11 @@ final class PhabricatorFileTransformController
unset($unguarded);
}
private function loadTransform($source_phid, $transform) {
return id(new PhabricatorTransformedFile())->loadOneWhere(
'originalPHID = %s AND transform = %s',
$source_phid,
$transform);
}
}