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

Move connection cache from "AphrontDatabaseConnection"-level to "LiskDAO"-level

Summary:
- Currently, connections are responsible for connection caching. However, I want unit tests to be able to say "throw away the entire connection cache" with storage fixtures, and this is difficult/impossible when connections are responsible for the cache.
- The only behavioral change is that previously we would use the same connection for read-mode and write-mode queries. We'll now establish two connections. No installs actually differentiate between the modes so it isn't particularly relevant what we do here. In the long term, we should probably check the "w" cache before building a new "r" connection, so transactional code which involves reads and writes works (we don't have any such code right now).

Test Plan: Loaded pages, verified only one connection was established per database. Ran unit tests.

Reviewers: btrahan, vrana, jungejason, edward

Reviewed By: vrana

CC: aran

Maniphest Tasks: T140

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

+81 -29
+4
src/applications/base/storage/lisk/PhabricatorLiskDAO.php
··· 138 138 * @task config 139 139 */ 140 140 abstract public function getApplicationName(); 141 + 142 + protected function getConnectionNamespace() { 143 + return self::$namespace.'_'.$this->getApplicationName(); 144 + } 141 145 }
-22
src/storage/connection/mysql/base/AphrontMySQLDatabaseConnectionBase.php
··· 27 27 28 28 private $nextError; 29 29 30 - private static $connectionCache = array(); 31 - 32 30 abstract protected function connect(); 33 31 abstract protected function rawQuery($raw_query); 34 32 abstract protected function fetchAssoc($result); ··· 83 81 private function closeConnection() { 84 82 if ($this->connection) { 85 83 $this->connection = null; 86 - $key = $this->getConnectionCacheKey(); 87 - unset(self::$connectionCache[$key]); 88 84 } 89 85 } 90 86 91 - private function getConnectionCacheKey() { 92 - $user = $this->getConfiguration('user'); 93 - $host = $this->getConfiguration('host'); 94 - $database = $this->getConfiguration('database'); 95 - 96 - return "{$user}:{$host}:{$database}"; 97 - } 98 - 99 87 private function establishConnection() { 100 - $this->closeConnection(); 101 - 102 - $key = $this->getConnectionCacheKey(); 103 - if (isset(self::$connectionCache[$key])) { 104 - $this->connection = self::$connectionCache[$key]; 105 - return; 106 - } 107 - 108 88 $start = microtime(true); 109 89 110 90 $host = $this->getConfiguration('host'); 111 91 $database = $this->getConfiguration('database'); 112 - 113 92 114 93 $profiler = PhutilServiceProfiler::getInstance(); 115 94 $call_id = $profiler->beginServiceCall( ··· 137 116 } 138 117 } 139 118 140 - self::$connectionCache[$key] = $conn; 141 119 $this->connection = $conn; 142 120 } 143 121
+73 -7
src/storage/lisk/dao/LiskDAO.php
··· 159 159 * Assuming ##$obj##, ##$other## and ##$another## live on the same database, 160 160 * this code will work correctly by establishing savepoints. 161 161 * 162 + * @task conn Managing Connections 162 163 * @task config Configuring Lisk 163 164 * @task load Loading Objects 164 165 * @task info Examining Objects ··· 187 188 const IDS_PHID = 'ids-phid'; 188 189 const IDS_MANUAL = 'ids-manual'; 189 190 190 - private $__connections = array(); 191 191 private $__dirtyFields = array(); 192 192 private $__missingFields = array(); 193 193 private static $processIsolationLevel = 0; 194 194 private static $__checkedClasses = array(); 195 195 196 196 private $__ephemeral = false; 197 + 198 + private static $connections = array(); 197 199 198 200 /** 199 201 * Build an empty object. ··· 235 237 } 236 238 } 237 239 240 + 241 + /* -( Managing Connections )----------------------------------------------- */ 242 + 243 + 244 + /** 245 + * Establish a live connection to a database service. This method should 246 + * return a new connection. Lisk handles connection caching and management; 247 + * do not perform caching deeper in the stack. 248 + * 249 + * @param string Mode, either 'r' (reading) or 'w' (reading and writing). 250 + * @return AphrontDatabaseConnection New database connection. 251 + * @task conn 252 + */ 238 253 abstract protected function establishLiveConnection($mode); 254 + 255 + 256 + /** 257 + * Return a namespace for this object's connections in the connection cache. 258 + * Generally, the database name is appropriate. Two connections are considered 259 + * equivalent if they have the same connection namespace and mode. 260 + * 261 + * @return string Connection namespace for cache 262 + * @task conn 263 + */ 264 + abstract protected function getConnectionNamespace(); 265 + 266 + 267 + /** 268 + * Get an existing, cached connection for this object. 269 + * 270 + * @param mode Connection mode. 271 + * @return AprontDatabaseConnection|null Connection, if it exists in cache. 272 + * @task conn 273 + */ 274 + protected function getEstablishedConnection($mode) { 275 + $key = $this->getConnectionNamespace().':'.$mode; 276 + if (isset(self::$connections[$key])) { 277 + return self::$connections[$key]; 278 + } 279 + return null; 280 + } 281 + 282 + 283 + /** 284 + * Store a connection in the connection cache. 285 + * 286 + * @param mode Connection mode. 287 + * @param AphrontDatabaseConnection Connection to cache. 288 + * @return this 289 + * @task conn 290 + */ 291 + protected function setEstablishedConnection( 292 + $mode, 293 + AphrontDatabaseConnection $connection) { 294 + 295 + $key = $this->getConnectionNamespace().':'.$mode; 296 + self::$connections[$key] = $connection; 297 + return $this; 298 + } 239 299 240 300 241 301 /* -( Configuring Lisk )--------------------------------------------------- */ ··· 739 799 740 800 if (self::shouldIsolateAllLiskEffectsToCurrentProcess()) { 741 801 $mode = 'isolate-'.$mode; 742 - if (!isset($this->__connections[$mode])) { 743 - $this->__connections[$mode] = $this->establishIsolatedConnection($mode); 802 + 803 + $connection = $this->getEstablishedConnection($mode); 804 + if (!$connection) { 805 + $connection = $this->establishIsolatedConnection($mode); 806 + $this->setEstablishedConnection($mode, $connection); 744 807 } 745 - return $this->__connections[$mode]; 808 + 809 + return $connection; 746 810 } 747 811 748 812 // TODO There is currently no protection on 'r' queries against writing 749 813 // or on 'w' queries against reading 750 814 751 - if (!isset($this->__connections[$mode])) { 752 - $this->__connections[$mode] = $this->establishLiveConnection($mode); 815 + $connection = $this->getEstablishedConnection($mode); 816 + if (!$connection) { 817 + $connection = $this->establishLiveConnection($mode); 818 + $this->setEstablishedConnection($mode, $connection); 753 819 } 754 820 755 - return $this->__connections[$mode]; 821 + return $connection; 756 822 } 757 823 758 824
+4
src/storage/lisk/dao/__tests__/LiskIsolationTestDAO.php
··· 37 37 "resource!"); 38 38 } 39 39 40 + public function getConnectionNamespace() { 41 + return 'test'; 42 + } 43 + 40 44 public function getTableName() { 41 45 return 'test'; 42 46 }