@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.

Introduce a request cache mechanism

Summary:
Ref T8424. This adds a standard KeyValueCache to serve as a request cache.

In particular, I need to cache Spaces (they are frequently accessed, sometimes by multiple viewers) but not have them survive longer than the scope of one request.

This request cache is explicitly destroyed by each web request and each daemon request.

In the very long term, building this kind of construct supports reusing PHP interpreters to run web requests (see some discussion in T2312).

Test Plan:
- Added and executed unit tests.
- Ran every daemon.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T8424

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

+90 -1
+2
src/__phutil_library_map__.php
··· 1495 1495 'PhabricatorCacheSpec' => 'applications/cache/spec/PhabricatorCacheSpec.php', 1496 1496 'PhabricatorCacheTTLGarbageCollector' => 'applications/cache/garbagecollector/PhabricatorCacheTTLGarbageCollector.php', 1497 1497 'PhabricatorCaches' => 'applications/cache/PhabricatorCaches.php', 1498 + 'PhabricatorCachesTestCase' => 'applications/cache/__tests__/PhabricatorCachesTestCase.php', 1498 1499 'PhabricatorCalendarApplication' => 'applications/calendar/application/PhabricatorCalendarApplication.php', 1499 1500 'PhabricatorCalendarController' => 'applications/calendar/controller/PhabricatorCalendarController.php', 1500 1501 'PhabricatorCalendarDAO' => 'applications/calendar/storage/PhabricatorCalendarDAO.php', ··· 4852 4853 'PhabricatorCacheSetupCheck' => 'PhabricatorSetupCheck', 4853 4854 'PhabricatorCacheSpec' => 'Phobject', 4854 4855 'PhabricatorCacheTTLGarbageCollector' => 'PhabricatorGarbageCollector', 4856 + 'PhabricatorCachesTestCase' => 'PhabricatorTestCase', 4855 4857 'PhabricatorCalendarApplication' => 'PhabricatorApplication', 4856 4858 'PhabricatorCalendarController' => 'PhabricatorController', 4857 4859 'PhabricatorCalendarDAO' => 'PhabricatorLiskDAO',
+36 -1
src/applications/cache/PhabricatorCaches.php
··· 1 1 <?php 2 2 3 3 /** 4 + * 5 + * @task request Request Cache 4 6 * @task immutable Immutable Cache 5 7 * @task setup Setup Cache 6 8 * @task compress Compression 7 9 */ 8 10 final class PhabricatorCaches { 11 + 12 + private static $requestCache; 9 13 10 14 public static function getNamespace() { 11 15 return PhabricatorEnv::getEnvConfig('phabricator.cache-namespace'); ··· 18 22 ->setCaches($caches); 19 23 } 20 24 25 + /* -( Request Cache )------------------------------------------------------ */ 21 26 22 - /* -( Local Cache )-------------------------------------------------------- */ 27 + 28 + /** 29 + * Get a request cache stack. 30 + * 31 + * This cache stack is destroyed after each logical request. In particular, 32 + * it is destroyed periodically by the daemons, while `static` caches are 33 + * not. 34 + * 35 + * @return PhutilKeyValueCacheStack Request cache stack. 36 + */ 37 + public static function getRequestCache() { 38 + if (!self::$requestCache) { 39 + self::$requestCache = new PhutilInRequestKeyValueCache(); 40 + } 41 + return self::$requestCache; 42 + } 43 + 44 + 45 + /** 46 + * Destroy the request cache. 47 + * 48 + * This is called at the beginning of each logical request. 49 + * 50 + * @return void 51 + */ 52 + public static function destroyRequestCache() { 53 + self::$requestCache = null; 54 + } 55 + 56 + 57 + /* -( Immutable Cache )---------------------------------------------------- */ 23 58 24 59 25 60 /**
+41
src/applications/cache/__tests__/PhabricatorCachesTestCase.php
··· 1 + <?php 2 + 3 + final class PhabricatorCachesTestCase 4 + extends PhabricatorTestCase { 5 + 6 + public function testRequestCache() { 7 + $cache = PhabricatorCaches::getRequestCache(); 8 + 9 + $test_key = 'unit.'.Filesystem::readRandomCharacters(8); 10 + 11 + $default_value = pht('Default'); 12 + $new_value = pht('New Value'); 13 + 14 + $this->assertEqual( 15 + $default_value, 16 + $cache->getKey($test_key, $default_value)); 17 + 18 + // Set a key, verify it persists. 19 + $cache = PhabricatorCaches::getRequestCache(); 20 + $cache->setKey($test_key, $new_value); 21 + $this->assertEqual( 22 + $new_value, 23 + $cache->getKey($test_key, $default_value)); 24 + 25 + // Refetch the cache, verify it's really a cache. 26 + $cache = PhabricatorCaches::getRequestCache(); 27 + $this->assertEqual( 28 + $new_value, 29 + $cache->getKey($test_key, $default_value)); 30 + 31 + // Destroy the cache. 32 + PhabricatorCaches::destroyRequestCache(); 33 + 34 + // Now, the value should be missing again. 35 + $cache = PhabricatorCaches::getRequestCache(); 36 + $this->assertEqual( 37 + $default_value, 38 + $cache->getKey($test_key, $default_value)); 39 + } 40 + 41 + }
+2
src/applications/fact/daemon/PhabricatorFactDaemon.php
··· 9 9 protected function run() { 10 10 $this->setEngines(PhabricatorFactEngine::loadAllEngines()); 11 11 while (!$this->shouldExit()) { 12 + PhabricatorCaches::destroyRequestCache(); 13 + 12 14 $iterators = $this->getAllApplicationIterators(); 13 15 foreach ($iterators as $iterator_name => $iterator) { 14 16 $this->processIteratorWithCursor($iterator_name, $iterator);
+1
src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php
··· 73 73 $queue = array(); 74 74 75 75 while (!$this->shouldExit()) { 76 + PhabricatorCaches::destroyRequestCache(); 76 77 $pullable = $this->loadPullableRepositories($include, $exclude); 77 78 78 79 // If any repositories have the NEEDS_UPDATE flag set, pull them
+2
src/infrastructure/daemon/bot/PhabricatorBot.php
··· 106 106 107 107 private function runLoop() { 108 108 do { 109 + PhabricatorCaches::destroyRequestCache(); 110 + 109 111 $this->stillWorking(); 110 112 111 113 $messages = $this->protocolAdapter->getNextMessages($this->pollFrequency);
+2
src/infrastructure/daemon/workers/PhabricatorTaskmasterDaemon.php
··· 4 4 5 5 protected function run() { 6 6 do { 7 + PhabricatorCaches::destroyRequestCache(); 8 + 7 9 $tasks = id(new PhabricatorWorkerLeaseQuery()) 8 10 ->setLimit(1) 9 11 ->execute();
+2
src/infrastructure/daemon/workers/PhabricatorTriggerDaemon.php
··· 65 65 $this->nextCollection = PhabricatorTime::getNow(); 66 66 67 67 do { 68 + PhabricatorCaches::destroyRequestCache(); 69 + 68 70 $lock = PhabricatorGlobalLock::newLock('trigger'); 69 71 70 72 try {
+2
webroot/index.php
··· 13 13 14 14 try { 15 15 PhabricatorStartup::loadCoreLibraries(); 16 + PhabricatorCaches::destroyRequestCache(); 17 + 16 18 $sink = new AphrontPHPHTTPSink(); 17 19 18 20 try {