mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-26 00:32:41 +01:00
Make the "result" property on Future private
Summary: Depends on D21033. Ref T11968. This is just an incremental step in modernizing Future and making it more robust. Currently, subclasses are expected to write directly to `$this->result`, but this isn't consistent with how modern classes generally work. Test Plan: Ran unit tests, created this revision. Maniphest Tasks: T11968 Differential Revision: https://secure.phabricator.com/D21034
This commit is contained in:
parent
e20dce875c
commit
4d55067fd8
7 changed files with 80 additions and 55 deletions
|
@ -7,7 +7,9 @@
|
||||||
*/
|
*/
|
||||||
abstract class Future extends Phobject {
|
abstract class Future extends Phobject {
|
||||||
|
|
||||||
protected $result;
|
private $hasResult = false;
|
||||||
|
private $result;
|
||||||
|
|
||||||
protected $exception;
|
protected $exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,22 +81,6 @@ abstract class Future extends Phobject {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the final result of the future. This method will be called after
|
|
||||||
* the future is ready (as per @{method:isReady}) but before results are
|
|
||||||
* passed back to the caller. The major use of this function is that you can
|
|
||||||
* override it in subclasses to do postprocessing or error checking, which is
|
|
||||||
* particularly useful if building application-specific futures on top of
|
|
||||||
* primitive transport futures (like @{class:CurlFuture} and
|
|
||||||
* @{class:ExecFuture}) which can make it tricky to hook this logic into the
|
|
||||||
* main pipeline.
|
|
||||||
*
|
|
||||||
* @return mixed Final resolution of this future.
|
|
||||||
*/
|
|
||||||
protected function getResult() {
|
|
||||||
return $this->result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default amount of time to wait on stream select for this future. Normally
|
* Default amount of time to wait on stream select for this future. Normally
|
||||||
* 1 second is fine, but if the future has a timeout sooner than that it
|
* 1 second is fine, but if the future has a timeout sooner than that it
|
||||||
|
@ -109,4 +95,38 @@ abstract class Future extends Phobject {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the final result of the future.
|
||||||
|
*
|
||||||
|
* @return wild Final resolution of this future.
|
||||||
|
*/
|
||||||
|
final protected function getResult() {
|
||||||
|
if (!$this->hasResult()) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Future has not yet resolved. Resolve futures before retrieving '.
|
||||||
|
'results.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected function setResult($result) {
|
||||||
|
if ($this->hasResult()) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Future has already resolved. Futures may not resolve more than '.
|
||||||
|
'once.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->hasResult = true;
|
||||||
|
$this->result = $result;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected function hasResult() {
|
||||||
|
return $this->hasResult;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,9 @@ abstract class FutureProxy extends Future {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function resolve() {
|
public function resolve() {
|
||||||
$this->getProxiedFuture()->resolve();
|
$result = $this->getProxiedFuture()->resolve();
|
||||||
|
$result = $this->didReceiveResult($result);
|
||||||
|
$this->setResult($result);
|
||||||
return $this->getResult();
|
return $this->getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,15 +54,6 @@ abstract class FutureProxy extends Future {
|
||||||
return $this->getProxiedFuture()->getWriteSockets();
|
return $this->getProxiedFuture()->getWriteSockets();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getResult() {
|
|
||||||
if ($this->result === null) {
|
|
||||||
$result = $this->getProxiedFuture()->resolve();
|
|
||||||
$result = $this->didReceiveResult($result);
|
|
||||||
$this->result = $result;
|
|
||||||
}
|
|
||||||
return $this->result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function start() {
|
public function start() {
|
||||||
$this->getProxiedFuture()->start();
|
$this->getProxiedFuture()->start();
|
||||||
return $this;
|
return $this;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
final class ImmediateFuture extends Future {
|
final class ImmediateFuture extends Future {
|
||||||
|
|
||||||
public function __construct($result) {
|
public function __construct($result) {
|
||||||
$this->result = $result;
|
$this->setResult($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isReady() {
|
public function isReady() {
|
||||||
|
|
|
@ -381,22 +381,25 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
* @task resolve
|
* @task resolve
|
||||||
*/
|
*/
|
||||||
public function resolveKill() {
|
public function resolveKill() {
|
||||||
if (!$this->result) {
|
if (!$this->hasResult()) {
|
||||||
$signal = 9;
|
$signal = 9;
|
||||||
|
|
||||||
if ($this->proc) {
|
if ($this->proc) {
|
||||||
proc_terminate($this->proc, $signal);
|
proc_terminate($this->proc, $signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->result = array(
|
$result = array(
|
||||||
128 + $signal,
|
128 + $signal,
|
||||||
$this->stdout,
|
$this->stdout,
|
||||||
$this->stderr,
|
$this->stderr,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$this->setResult($result);
|
||||||
|
|
||||||
$this->closeProcess();
|
$this->closeProcess();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->result;
|
return $this->getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -764,11 +767,14 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->result = array(
|
$result = array(
|
||||||
$err,
|
$err,
|
||||||
$this->stdout,
|
$this->stdout,
|
||||||
$this->stderr,
|
$this->stderr,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$this->setResult($result);
|
||||||
|
|
||||||
$this->closeProcess();
|
$this->closeProcess();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -839,11 +845,18 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
unset($this->windowsStderrTempFile);
|
unset($this->windowsStderrTempFile);
|
||||||
|
|
||||||
if ($this->profilerCallID !== null) {
|
if ($this->profilerCallID !== null) {
|
||||||
|
if ($this->hasResult()) {
|
||||||
|
$result = $this->getResult();
|
||||||
|
$err = idx($result, 0);
|
||||||
|
} else {
|
||||||
|
$err = null;
|
||||||
|
}
|
||||||
|
|
||||||
$profiler = PhutilServiceProfiler::getInstance();
|
$profiler = PhutilServiceProfiler::getInstance();
|
||||||
$profiler->endServiceCall(
|
$profiler->endServiceCall(
|
||||||
$this->profilerCallID,
|
$this->profilerCallID,
|
||||||
array(
|
array(
|
||||||
'err' => $this->result ? idx($this->result, 0) : null,
|
'err' => $err,
|
||||||
));
|
));
|
||||||
$this->profilerCallID = null;
|
$this->profilerCallID = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,6 @@
|
||||||
*/
|
*/
|
||||||
final class PhutilExecPassthru extends PhutilExecutableFuture {
|
final class PhutilExecPassthru extends PhutilExecutableFuture {
|
||||||
|
|
||||||
private $passthruResult;
|
|
||||||
|
|
||||||
|
|
||||||
/* -( Executing Passthru Commands )---------------------------------------- */
|
/* -( Executing Passthru Commands )---------------------------------------- */
|
||||||
|
|
||||||
|
@ -105,15 +103,12 @@ final class PhutilExecPassthru extends PhutilExecutableFuture {
|
||||||
// full control of the console. We're just implementing the interfaces to
|
// full control of the console. We're just implementing the interfaces to
|
||||||
// make it easier to share code with ExecFuture.
|
// make it easier to share code with ExecFuture.
|
||||||
|
|
||||||
if ($this->passthruResult === null) {
|
if (!$this->hasResult()) {
|
||||||
$this->passthruResult = $this->execute();
|
$result = $this->execute();
|
||||||
|
$this->setResult($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getResult() {
|
|
||||||
return $this->passthruResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,8 +180,9 @@ final class HTTPFuture extends BaseHTTPFuture {
|
||||||
|
|
||||||
if (!$socket) {
|
if (!$socket) {
|
||||||
$this->stateReady = true;
|
$this->stateReady = true;
|
||||||
$this->result = $this->buildErrorResult(
|
$this->setResult(
|
||||||
HTTPFutureTransportResponseStatus::ERROR_CONNECTION_FAILED);
|
$this->buildErrorResult(
|
||||||
|
HTTPFutureTransportResponseStatus::ERROR_CONNECTION_FAILED));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,16 +210,19 @@ final class HTTPFuture extends BaseHTTPFuture {
|
||||||
$this->stateReady = true;
|
$this->stateReady = true;
|
||||||
|
|
||||||
if ($timeout) {
|
if ($timeout) {
|
||||||
$this->result = $this->buildErrorResult(
|
$this->setResult(
|
||||||
HTTPFutureTransportResponseStatus::ERROR_TIMEOUT);
|
$this->buildErrorResult(
|
||||||
|
HTTPFutureTransportResponseStatus::ERROR_TIMEOUT));
|
||||||
} else if (!$this->stateConnected) {
|
} else if (!$this->stateConnected) {
|
||||||
$this->result = $this->buildErrorResult(
|
$this->setResult(
|
||||||
HTTPFutureTransportResponseStatus::ERROR_CONNECTION_REFUSED);
|
$this->buildErrorResult(
|
||||||
|
HTTPFutureTransportResponseStatus::ERROR_CONNECTION_REFUSED));
|
||||||
} else if (!$this->stateWriteComplete) {
|
} else if (!$this->stateWriteComplete) {
|
||||||
$this->result = $this->buildErrorResult(
|
$this->setResult(
|
||||||
HTTPFutureTransportResponseStatus::ERROR_CONNECTION_FAILED);
|
$this->buildErrorResult(
|
||||||
|
HTTPFutureTransportResponseStatus::ERROR_CONNECTION_FAILED));
|
||||||
} else {
|
} else {
|
||||||
$this->result = $this->parseRawHTTPResponse($this->response);
|
$this->setResult($this->parseRawHTTPResponse($this->response));
|
||||||
}
|
}
|
||||||
|
|
||||||
$profiler = PhutilServiceProfiler::getInstance();
|
$profiler = PhutilServiceProfiler::getInstance();
|
||||||
|
|
|
@ -194,7 +194,7 @@ final class HTTPSFuture extends BaseHTTPFuture {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isReady() {
|
public function isReady() {
|
||||||
if (isset($this->result)) {
|
if ($this->hasResult()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,7 +476,7 @@ final class HTTPSFuture extends BaseHTTPFuture {
|
||||||
|
|
||||||
$body = null;
|
$body = null;
|
||||||
$headers = array();
|
$headers = array();
|
||||||
$this->result = array($status, $body, $headers);
|
$this->setResult(array($status, $body, $headers));
|
||||||
} else if ($this->parser) {
|
} else if ($this->parser) {
|
||||||
$streaming_parser = $this->parser;
|
$streaming_parser = $this->parser;
|
||||||
try {
|
try {
|
||||||
|
@ -491,12 +491,12 @@ final class HTTPSFuture extends BaseHTTPFuture {
|
||||||
$result = array($ex, null, array());
|
$result = array($ex, null, array());
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->result = $result;
|
$this->setResult($result);
|
||||||
} else {
|
} else {
|
||||||
// cURL returns headers of all redirects, we strip all but the final one.
|
// cURL returns headers of all redirects, we strip all but the final one.
|
||||||
$redirects = curl_getinfo($curl, CURLINFO_REDIRECT_COUNT);
|
$redirects = curl_getinfo($curl, CURLINFO_REDIRECT_COUNT);
|
||||||
$result = preg_replace('/^(.*\r\n\r\n){'.$redirects.'}/sU', '', $result);
|
$result = preg_replace('/^(.*\r\n\r\n){'.$redirects.'}/sU', '', $result);
|
||||||
$this->result = $this->parseRawHTTPResponse($result);
|
$this->setResult($this->parseRawHTTPResponse($result));
|
||||||
}
|
}
|
||||||
|
|
||||||
curl_multi_remove_handle(self::$multi, $curl);
|
curl_multi_remove_handle(self::$multi, $curl);
|
||||||
|
@ -518,7 +518,7 @@ final class HTTPSFuture extends BaseHTTPFuture {
|
||||||
|
|
||||||
$sink = $this->getProgressSink();
|
$sink = $this->getProgressSink();
|
||||||
if ($sink) {
|
if ($sink) {
|
||||||
$status = head($this->result);
|
$status = head($this->getResult());
|
||||||
if ($status->isError()) {
|
if ($status->isError()) {
|
||||||
$sink->didFailWork();
|
$sink->didFailWork();
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue