mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-24 22:40:55 +01:00
f45a13cff4
Summary: Ref T11954. This reduces how much work we need to do to load settings, particularly for Conduit (which currently can not benefit directly from the user cache, because it loads the user indirectly via a token). Specifically: - Cache builtin defaults in the runtime cache. This means Phabricator may need to be restarted if you change a global setting default, but this is exceptionally rare. - Cache global defaults in the mutable cache. This means we do less work to load them. - Avoid loading settings classes if we don't have to. - If we missed the user cache for settings, try to read it from the cache table before we actually go regenerate it (we miss on Conduit pathways). Test Plan: Used `ab -n100 ...` to observe a ~6-10ms performance improvement for `user.whoami`. Reviewers: chad Reviewed By: chad Maniphest Tasks: T11954 Differential Revision: https://secure.phabricator.com/D16998
166 lines
3.8 KiB
PHP
166 lines
3.8 KiB
PHP
<?php
|
|
|
|
final class PhabricatorUserCache extends PhabricatorUserDAO {
|
|
|
|
protected $userPHID;
|
|
protected $cacheIndex;
|
|
protected $cacheKey;
|
|
protected $cacheData;
|
|
protected $cacheType;
|
|
|
|
protected function getConfiguration() {
|
|
return array(
|
|
self::CONFIG_TIMESTAMPS => false,
|
|
self::CONFIG_COLUMN_SCHEMA => array(
|
|
'cacheIndex' => 'bytes12',
|
|
'cacheKey' => 'text255',
|
|
'cacheData' => 'text',
|
|
'cacheType' => 'text32',
|
|
),
|
|
self::CONFIG_KEY_SCHEMA => array(
|
|
'key_usercache' => array(
|
|
'columns' => array('userPHID', 'cacheIndex'),
|
|
'unique' => true,
|
|
),
|
|
'key_cachekey' => array(
|
|
'columns' => array('cacheIndex'),
|
|
),
|
|
'key_cachetype' => array(
|
|
'columns' => array('cacheType'),
|
|
),
|
|
),
|
|
) + parent::getConfiguration();
|
|
}
|
|
|
|
public function save() {
|
|
$this->cacheIndex = Filesystem::digestForIndex($this->getCacheKey());
|
|
return parent::save();
|
|
}
|
|
|
|
public static function writeCache(
|
|
PhabricatorUserCacheType $type,
|
|
$key,
|
|
$user_phid,
|
|
$raw_value) {
|
|
self::writeCaches(
|
|
array(
|
|
array(
|
|
'type' => $type,
|
|
'key' => $key,
|
|
'userPHID' => $user_phid,
|
|
'value' => $raw_value,
|
|
),
|
|
));
|
|
}
|
|
|
|
public static function writeCaches(array $values) {
|
|
if (PhabricatorEnv::isReadOnly()) {
|
|
return;
|
|
}
|
|
|
|
if (!$values) {
|
|
return;
|
|
}
|
|
|
|
$table = new self();
|
|
$conn_w = $table->establishConnection('w');
|
|
|
|
$sql = array();
|
|
foreach ($values as $value) {
|
|
$key = $value['key'];
|
|
|
|
$sql[] = qsprintf(
|
|
$conn_w,
|
|
'(%s, %s, %s, %s, %s)',
|
|
$value['userPHID'],
|
|
PhabricatorHash::digestForIndex($key),
|
|
$key,
|
|
$value['value'],
|
|
$value['type']->getUserCacheType());
|
|
}
|
|
|
|
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
|
|
|
foreach (PhabricatorLiskDAO::chunkSQL($sql) as $chunk) {
|
|
queryfx(
|
|
$conn_w,
|
|
'INSERT INTO %T (userPHID, cacheIndex, cacheKey, cacheData, cacheType)
|
|
VALUES %Q
|
|
ON DUPLICATE KEY UPDATE
|
|
cacheData = VALUES(cacheData),
|
|
cacheType = VALUES(cacheType)',
|
|
$table->getTableName(),
|
|
$chunk);
|
|
}
|
|
|
|
unset($unguarded);
|
|
}
|
|
|
|
public static function readCaches(
|
|
PhabricatorUserCacheType $type,
|
|
$key,
|
|
array $user_phids) {
|
|
|
|
$table = new self();
|
|
$conn = $table->establishConnection('r');
|
|
|
|
$rows = queryfx_all(
|
|
$conn,
|
|
'SELECT userPHID, cacheData FROM %T WHERE userPHID IN (%Ls)
|
|
AND cacheType = %s AND cacheIndex = %s',
|
|
$table->getTableName(),
|
|
$user_phids,
|
|
$type->getUserCacheType(),
|
|
PhabricatorHash::digestForIndex($key));
|
|
|
|
return ipull($rows, 'cacheData', 'userPHID');
|
|
}
|
|
|
|
public static function clearCache($key, $user_phid) {
|
|
return self::clearCaches($key, array($user_phid));
|
|
}
|
|
|
|
public static function clearCaches($key, array $user_phids) {
|
|
if (PhabricatorEnv::isReadOnly()) {
|
|
return;
|
|
}
|
|
|
|
if (!$user_phids) {
|
|
return;
|
|
}
|
|
|
|
$table = new self();
|
|
$conn_w = $table->establishConnection('w');
|
|
|
|
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
|
|
|
queryfx(
|
|
$conn_w,
|
|
'DELETE FROM %T WHERE cacheIndex = %s AND userPHID IN (%Ls)',
|
|
$table->getTableName(),
|
|
PhabricatorHash::digestForIndex($key),
|
|
$user_phids);
|
|
|
|
unset($unguarded);
|
|
}
|
|
|
|
public static function clearCacheForAllUsers($key) {
|
|
if (PhabricatorEnv::isReadOnly()) {
|
|
return;
|
|
}
|
|
|
|
$table = new self();
|
|
$conn_w = $table->establishConnection('w');
|
|
|
|
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
|
|
|
queryfx(
|
|
$conn_w,
|
|
'DELETE FROM %T WHERE cacheIndex = %s',
|
|
$table->getTableName(),
|
|
PhabricatorHash::digestForIndex($key));
|
|
|
|
unset($unguarded);
|
|
}
|
|
|
|
}
|