@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
at recaptime-dev/main 125 lines 3.3 kB view raw
1<?php 2 3final class PhabricatorSearchWorker extends PhabricatorWorker { 4 5 public static function queueDocumentForIndexing( 6 $phid, 7 $parameters = null, 8 $is_strict = false) { 9 10 if ($parameters === null) { 11 $parameters = array(); 12 } 13 14 parent::scheduleTask( 15 self::class, 16 array( 17 'documentPHID' => $phid, 18 'parameters' => $parameters, 19 'strict' => $is_strict, 20 ), 21 array( 22 'priority' => parent::PRIORITY_INDEX, 23 'objectPHID' => $phid, 24 )); 25 } 26 27 protected function doWork() { 28 $data = $this->getTaskData(); 29 $object_phid = idx($data, 'documentPHID'); 30 31 // See T12425. By the time we run an indexing task, the object it indexes 32 // may have been deleted. This is unusual, but not concerning, and failing 33 // to index these objects is correct. 34 35 // To avoid showing these non-actionable errors to users, don't report 36 // indexing exceptions unless we're in "strict" mode. This mode is set by 37 // the "bin/search index" tool. 38 39 $is_strict = idx($data, 'strict', false); 40 41 try { 42 $object = $this->loadObjectForIndexing($object_phid); 43 } catch (PhabricatorWorkerPermanentFailureException $ex) { 44 if ($is_strict) { 45 throw $ex; 46 } else { 47 return; 48 } 49 } 50 51 $engine = id(new PhabricatorIndexEngine()) 52 ->setObject($object); 53 54 $parameters = idx($data, 'parameters', array()); 55 $engine->setParameters($parameters); 56 57 if (!$engine->shouldIndexObject()) { 58 return; 59 } 60 61 $lock = PhabricatorGlobalLock::newLock( 62 'index', 63 array( 64 'objectPHID' => $object_phid, 65 )); 66 67 try { 68 $lock->lock(1); 69 } catch (PhutilLockException $ex) { 70 // If we fail to acquire the lock, just yield. It's expected that we may 71 // contend on this lock occasionally if a large object receives many 72 // updates in a short period of time, and it's appropriate to just retry 73 // rebuilding the index later. 74 throw new PhabricatorWorkerYieldException(15); 75 } 76 77 $caught = null; 78 try { 79 // Reload the object now that we have a lock, to make sure we have the 80 // most current version. 81 $object = $this->loadObjectForIndexing($object->getPHID()); 82 83 $engine->setObject($object); 84 $engine->indexObject(); 85 } catch (Exception $ex) { 86 $caught = $ex; 87 } 88 89 // Release the lock before we deal with the exception. 90 $lock->unlock(); 91 92 if ($caught) { 93 if (!($caught instanceof PhabricatorWorkerPermanentFailureException)) { 94 $caught = new PhabricatorWorkerPermanentFailureException( 95 pht( 96 'Failed to update search index for document "%s": %s', 97 $object_phid, 98 $caught->getMessage())); 99 } 100 101 if ($is_strict) { 102 throw $caught; 103 } 104 } 105 } 106 107 private function loadObjectForIndexing($phid) { 108 $viewer = PhabricatorUser::getOmnipotentUser(); 109 110 $object = id(new PhabricatorObjectQuery()) 111 ->setViewer($viewer) 112 ->withPHIDs(array($phid)) 113 ->executeOne(); 114 115 if (!$object) { 116 throw new PhabricatorWorkerPermanentFailureException( 117 pht( 118 'Unable to load object "%s" to rebuild indexes.', 119 $phid)); 120 } 121 122 return $object; 123 } 124 125}