mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-24 14:30:56 +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:
parent
2ecdbbec10
commit
c39b64d963
5 changed files with 44 additions and 37 deletions
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue