@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Make query engines "overheat" instead of stalling when filtering too many results

Summary: Ref T11773. This is an initial first step toward a more complete solution, but should make the worst case much less bad: prior to this change, the worst case was "30 second exeuction timeout". After this patch, the worst case is "no results + explanatory message", which is strictly better.

Test Plan:
Made all feed stories fail policy checks, loaded home page.

- Before adding overheating: 9,600 queries / 20 seconds
- After adding overheating: 376 queries / 800ms

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T11773

Differential Revision: https://secure.phabricator.com/D16735

+54
+29
src/applications/search/controller/PhabricatorApplicationSearchController.php
··· 238 238 $nux_view = null; 239 239 } 240 240 241 + $is_overheated = $query->getIsOverheated(); 242 + 241 243 if ($nux_view) { 242 244 $box->appendChild($nux_view); 243 245 } else { ··· 263 265 } 264 266 if ($list->getContent()) { 265 267 $box->appendChild($list->getContent()); 268 + } 269 + 270 + if ($is_overheated) { 271 + $box->appendChild($this->newOverheatedView($objects)); 266 272 } 267 273 268 274 $result_header = $list->getHeader(); ··· 523 529 ->setText(pht('Use Results...')) 524 530 ->setIcon('fa-road') 525 531 ->setDropdownMenu($action_list); 532 + } 533 + 534 + private function newOverheatedView(array $results) { 535 + if ($results) { 536 + $message = pht( 537 + 'Most objects matching your query are not visible to you, so '. 538 + 'filtering results is taking a long time. Only some results are '. 539 + 'shown. Refine your query to find results more quickly.'); 540 + } else { 541 + $message = pht( 542 + 'Most objects matching your query are not visible to you, so '. 543 + 'filtering results is taking a long time. Refine your query to '. 544 + 'find results more quickly.'); 545 + } 546 + 547 + return id(new PHUIInfoView()) 548 + ->setSeverity(PHUIInfoView::SEVERITY_WARNING) 549 + ->setFlush(true) 550 + ->setTitle(pht('Query Overheated')) 551 + ->setErrors( 552 + array( 553 + $message, 554 + )); 526 555 } 527 556 528 557 }
+25
src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php
··· 44 44 * and `null` (inherit from parent query, with no exceptions by default). 45 45 */ 46 46 private $raisePolicyExceptions; 47 + private $isOverheated; 47 48 48 49 49 50 /* -( Query Configuration )------------------------------------------------ */ ··· 215 216 216 217 $this->willExecute(); 217 218 219 + // If we examine and filter significantly more objects than the query 220 + // limit, we stop early. This prevents us from looping through a huge 221 + // number of records when the viewer can see few or none of them. See 222 + // T11773 for some discussion. 223 + $this->isOverheated = false; 224 + $overheat_limit = $limit * 10; 225 + $total_seen = 0; 226 + 218 227 do { 219 228 if ($need) { 220 229 $this->rawResultLimit = min($need - $count, 1024); ··· 231 240 } else { 232 241 $page = array(); 233 242 } 243 + 244 + $total_seen += count($page); 234 245 235 246 if ($page) { 236 247 $maybe_visible = $this->willFilterPage($page); ··· 302 313 } 303 314 304 315 $this->nextPage($page); 316 + 317 + if ($overheat_limit && ($total_seen >= $overheat_limit)) { 318 + $this->isOverheated = true; 319 + break; 320 + } 305 321 } while (true); 306 322 307 323 $results = $this->didLoadResults($results); ··· 368 384 } 369 385 return $this; 370 386 } 387 + 388 + 389 + public function getIsOverheated() { 390 + if ($this->isOverheated === null) { 391 + throw new PhutilInvalidStateException('execute'); 392 + } 393 + return $this->isOverheated; 394 + } 395 + 371 396 372 397 /** 373 398 * Return a map of all object PHIDs which were loaded in the query but