1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-25 06:50:55 +01:00

Improve handle loading semantics for tokenizers

Summary:
Ref T7689. Fixes T7688. When there are a bunch of tokenizers with different values of the same object type (e.g. 5 tokenizers with users a, b, c, d, e) we currently issue 5 separate queries to load their handles.

Improve this behavior in the common case so we can usually batch these loads.

Test Plan:
  - In Maniphest, set the various search fields to different values.
  - Used DarkConsole to examine query plan.
  - Saw fewer queries after patch than before.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T7688, T7689

Differential Revision: https://secure.phabricator.com/D12261
This commit is contained in:
epriestley 2015-04-02 13:42:01 -07:00
parent 2ecdbbec10
commit c39b64d963
5 changed files with 44 additions and 37 deletions

View file

@ -89,10 +89,6 @@ abstract class AphrontTagView extends AphrontView {
return $this->renderChildren(); return $this->renderChildren();
} }
protected function willRender() {
return;
}
final public function render() { final public function render() {
$this->willRender(); $this->willRender();

View file

@ -149,6 +149,22 @@ abstract class AphrontView extends Phobject
/* -( Rendering )---------------------------------------------------------- */ /* -( Rendering )---------------------------------------------------------- */
/**
* Inconsistent, unreliable pre-rendering hook.
*
* This hook //may// fire before views render. It is not fired reliably, and
* may fire multiple times.
*
* If it does fire, views might use it to register data for later loads, but
* almost no datasources support this now; this is currently only useful for
* tokenizers. This mechanism might eventually see wider support or might be
* removed.
*/
public function willRender() {
return;
}
abstract public function render(); abstract public function render();

View file

@ -94,6 +94,7 @@ final class AphrontFormView extends AphrontView {
public function buildLayoutView() { public function buildLayoutView() {
foreach ($this->controls as $control) { foreach ($this->controls as $control) {
$control->setUser($this->getUser()); $control->setUser($this->getUser());
$control->willRender();
} }
return id(new PHUIFormLayoutView()) return id(new PHUIFormLayoutView())

View file

@ -6,6 +6,7 @@ final class AphrontFormTokenizerControl extends AphrontFormControl {
private $disableBehavior; private $disableBehavior;
private $limit; private $limit;
private $placeholder; private $placeholder;
private $handles;
public function setDatasource(PhabricatorTypeaheadDatasource $datasource) { public function setDatasource(PhabricatorTypeaheadDatasource $datasource) {
$this->datasource = $datasource; $this->datasource = $datasource;
@ -31,41 +32,17 @@ final class AphrontFormTokenizerControl extends AphrontFormControl {
return $this; return $this;
} }
public function willRender() {
// Load the handles now so we'll get a bulk load later on when we actually
// render them.
$this->loadHandles();
}
protected function renderInput() { protected function renderInput() {
$name = $this->getName(); $name = $this->getName();
$values = nonempty($this->getValue(), array());
// Values may either be handles (which are now legacy/deprecated) or $handles = $this->loadHandles();
// strings. Load handles for any PHIDs. $handles = iterator_to_array($handles);
$load = array();
$handles = array();
$select = array();
foreach ($values as $value) {
if ($value instanceof PhabricatorObjectHandle) {
$handles[$value->getPHID()] = $value;
$select[] = $value->getPHID();
} else {
$load[] = $value;
$select[] = $value;
}
}
// TODO: Once this code path simplifies, move this prefetch to setValue()
// so we can bulk load across multiple controls.
if ($load) {
$viewer = $this->getUser();
if (!$viewer) {
// TODO: Clean this up when handles go away.
throw new Exception(
pht('Call setUser() before rendering tokenizer string values.'));
}
$loaded_handles = $viewer->loadHandles($load);
$handles = $handles + iterator_to_array($loaded_handles);
}
// Reorder the list into input order.
$handles = array_select_keys($handles, $select);
if ($this->getID()) { if ($this->getID()) {
$id = $this->getID(); $id = $this->getID();
@ -112,4 +89,21 @@ final class AphrontFormTokenizerControl extends AphrontFormControl {
return $template->render(); return $template->render();
} }
private function loadHandles() {
if ($this->handles === null) {
$viewer = $this->getUser();
if (!$viewer) {
throw new Exception(
pht(
'Call setUser() before rendering tokenizers. Use appendControl() '.
'on AphrontFormView to do this easily.'));
}
$values = nonempty($this->getValue(), array());
$this->handles = $viewer->loadHandles($values);
}
return $this->handles;
}
} }

View file

@ -152,7 +152,7 @@ final class PHUIListView extends AphrontTagView {
return $this->items; return $this->items;
} }
protected function willRender() { public function willRender() {
$key_map = array(); $key_map = array();
foreach ($this->items as $item) { foreach ($this->items as $item) {
$key = $item->getKey(); $key = $item->getKey();