mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-22 06:42:41 +01:00
Improve resolution behaviors of FutureProxy
Summary: See PHI1764. See PHI1802. Address two resolution behaviors for FutureProxy: - FutureProxy may throw an exception directly from iteration via "FutureIterator" (see PHI1764). This is wrong: futures should throw only when resolved. - FutureProxy can not change an exception into a result, or a result into an exception, or an exception into a different exception. Being able to proxy the full range of result and exception behavior is useful, particularly for Conduit (see PHI1802). Make "FutureProxy" more robust in how it handles exceptions from proxied futures. Test Plan: Used this script to raise an exception during result processing: ``` <?php require_once 'support/init/init-script.php'; final class ThrowingFutureProxy extends FutureProxy { protected function didReceiveResult($result) { throw new Exception('!'); } } $future = new ImmediateFuture('quack'); $proxy = new ThrowingFutureProxy($future); $iterator = new FutureIterator(array($proxy)); foreach ($iterator as $resolved) { try { $resolved->resolve(); } catch (Exception $ex) { echo "Caught exception properly on resolution.\n"; } } ``` Before this change, the exception is raised in the `foreach()` loop. After this change, the exception is raised at resolution time. Differential Revision: https://secure.phabricator.com/D21383
This commit is contained in:
parent
98ca5cfa81
commit
2daf9b16ae
2 changed files with 19 additions and 13 deletions
|
@ -63,7 +63,7 @@ abstract class Future extends Phobject {
|
||||||
$this->hasStarted = true;
|
$this->hasStarted = true;
|
||||||
|
|
||||||
$this->startServiceProfiler();
|
$this->startServiceProfiler();
|
||||||
$this->isReady();
|
$this->updateFuture();
|
||||||
}
|
}
|
||||||
|
|
||||||
final public function updateFuture() {
|
final public function updateFuture() {
|
||||||
|
|
|
@ -27,27 +27,29 @@ abstract class FutureProxy extends Future {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isReady() {
|
public function isReady() {
|
||||||
if ($this->hasResult()) {
|
if ($this->hasResult() || $this->hasException()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$proxied = $this->getProxiedFuture();
|
$proxied = $this->getProxiedFuture();
|
||||||
|
$proxied->updateFuture();
|
||||||
|
|
||||||
$is_ready = $proxied->isReady();
|
if ($proxied->hasResult() || $proxied->hasException()) {
|
||||||
|
try {
|
||||||
|
$result = $proxied->resolve();
|
||||||
|
$result = $this->didReceiveResult($result);
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$result = $this->didReceiveException($ex);
|
||||||
|
} catch (Throwable $ex) {
|
||||||
|
$result = $this->didReceiveException($ex);
|
||||||
|
}
|
||||||
|
|
||||||
if ($proxied->hasResult()) {
|
|
||||||
$result = $proxied->getResult();
|
|
||||||
$result = $this->didReceiveResult($result);
|
|
||||||
$this->setResult($result);
|
$this->setResult($result);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $is_ready;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
public function resolve() {
|
|
||||||
$this->getProxiedFuture()->resolve();
|
|
||||||
$this->isReady();
|
|
||||||
return $this->getResult();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getReadSockets() {
|
public function getReadSockets() {
|
||||||
|
@ -73,4 +75,8 @@ abstract class FutureProxy extends Future {
|
||||||
|
|
||||||
abstract protected function didReceiveResult($result);
|
abstract protected function didReceiveResult($result);
|
||||||
|
|
||||||
|
protected function didReceiveException($exception) {
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue