mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-22 06:42:41 +01:00
Introduce "FuturePool" to make it easier to manage an ongoing pool of futures
Summary: Ref T11968. "FutureIterator" recently became non-rewindable, and starting a Future twice is now an error. This complicates a handful of use cases where a mostly-constant pool of futures is maintained over a long period of time, notably in daemon overseers and repository pull daemons. They previously relied on being able to do "new FutureIterator($futures)" to continue resolution of a list of futures from any state. This no longer works quite like it used to, since Futures generally may not belong to more than one iterator now (and this property is desirable). Introduce "FuturePool", which maintains exactly one iterator but manages the small amount of glue around adding and removing Futures from it, destroying it if the pool empties, and rebuilding it if the pool fills. Test Plan: See next change, which makes use of this. Maniphest Tasks: T11968 Differential Revision: https://secure.phabricator.com/D21053
This commit is contained in:
parent
368aec16a1
commit
099c2ae648
2 changed files with 69 additions and 0 deletions
|
@ -513,6 +513,7 @@ phutil_register_library_map(array(
|
||||||
'Future' => 'future/Future.php',
|
'Future' => 'future/Future.php',
|
||||||
'FutureIterator' => 'future/FutureIterator.php',
|
'FutureIterator' => 'future/FutureIterator.php',
|
||||||
'FutureIteratorTestCase' => 'future/__tests__/FutureIteratorTestCase.php',
|
'FutureIteratorTestCase' => 'future/__tests__/FutureIteratorTestCase.php',
|
||||||
|
'FuturePool' => 'future/FuturePool.php',
|
||||||
'FutureProxy' => 'future/FutureProxy.php',
|
'FutureProxy' => 'future/FutureProxy.php',
|
||||||
'HTTPFuture' => 'future/http/HTTPFuture.php',
|
'HTTPFuture' => 'future/http/HTTPFuture.php',
|
||||||
'HTTPFutureCURLResponseStatus' => 'future/http/status/HTTPFutureCURLResponseStatus.php',
|
'HTTPFutureCURLResponseStatus' => 'future/http/status/HTTPFutureCURLResponseStatus.php',
|
||||||
|
@ -1455,6 +1456,7 @@ phutil_register_library_map(array(
|
||||||
'Iterator',
|
'Iterator',
|
||||||
),
|
),
|
||||||
'FutureIteratorTestCase' => 'PhutilTestCase',
|
'FutureIteratorTestCase' => 'PhutilTestCase',
|
||||||
|
'FuturePool' => 'Phobject',
|
||||||
'FutureProxy' => 'Future',
|
'FutureProxy' => 'Future',
|
||||||
'HTTPFuture' => 'BaseHTTPFuture',
|
'HTTPFuture' => 'BaseHTTPFuture',
|
||||||
'HTTPFutureCURLResponseStatus' => 'HTTPFutureResponseStatus',
|
'HTTPFutureCURLResponseStatus' => 'HTTPFutureResponseStatus',
|
||||||
|
|
67
src/future/FuturePool.php
Normal file
67
src/future/FuturePool.php
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class FuturePool
|
||||||
|
extends Phobject {
|
||||||
|
|
||||||
|
private $shouldRewind;
|
||||||
|
private $iteratorTemplate;
|
||||||
|
private $iterator;
|
||||||
|
private $futures = array();
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->iteratorTemplate = new FutureIterator(array());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIteratorTemplate() {
|
||||||
|
return $this->iteratorTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addFuture(Future $future) {
|
||||||
|
$future_key = $future->getFutureKey();
|
||||||
|
|
||||||
|
if (!isset($this->futures[$future_key])) {
|
||||||
|
if (!$this->iterator) {
|
||||||
|
$this->iterator = clone $this->getIteratorTemplate();
|
||||||
|
$this->shouldRewind = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$iterator = $this->iterator;
|
||||||
|
$iterator->addFuture($future);
|
||||||
|
|
||||||
|
$this->futures[$future_key] = $future;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasFutures() {
|
||||||
|
return (bool)$this->futures;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resolve() {
|
||||||
|
$iterator = $this->iterator;
|
||||||
|
|
||||||
|
if (!$iterator) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->shouldRewind) {
|
||||||
|
$iterator->rewind();
|
||||||
|
$this->shouldRewind = false;
|
||||||
|
} else {
|
||||||
|
$iterator->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($iterator->valid()) {
|
||||||
|
$future_key = $iterator->key();
|
||||||
|
if ($future_key !== null) {
|
||||||
|
unset($this->futures[$future_key]);
|
||||||
|
}
|
||||||
|
return $iterator->current();
|
||||||
|
} else {
|
||||||
|
$this->iterator = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue