Store pkeys in cache for listGet()
I was storing the full objects in the cache for the listGet() function. I've changed it to store only pkeys, and use pivotGet() to get all the corresponding values. This also required changing pivotGet() so it can get objects with multi-column pkeys, which complicated the whole thing quite a bit. But it seems to work OK.
This commit is contained in:
parent
7ce2b3c756
commit
ed31052d26
@ -44,7 +44,7 @@ class Fave extends Memcached_DataObject
|
||||
common_log_db_error($fave, 'INSERT', __FILE__);
|
||||
return false;
|
||||
}
|
||||
self::blow('fave:list:notice_id:%d', $fave->notice_id);
|
||||
self::blow('fave:list-ids:notice_id:%d', $fave->notice_id);
|
||||
|
||||
Event::handle('EndFavorNotice', array($profile, $notice));
|
||||
}
|
||||
@ -62,7 +62,7 @@ class Fave extends Memcached_DataObject
|
||||
if (Event::handle('StartDisfavorNotice', array($profile, $notice, &$result))) {
|
||||
|
||||
$result = parent::delete();
|
||||
self::blow('fave:list:notice_id:%d', $this->notice_id);
|
||||
self::blow('fave:list-ids:notice_id:%d', $this->notice_id);
|
||||
|
||||
if ($result) {
|
||||
Event::handle('EndDisfavorNotice', array($profile, $notice));
|
||||
|
@ -105,18 +105,34 @@ class Memcached_DataObject extends Safe_DataObject
|
||||
*/
|
||||
static function pivotGet($cls, $keyCol, $keyVals, $otherCols = array())
|
||||
{
|
||||
$result = array_fill_keys($keyVals, null);
|
||||
if (is_array($keyCol)) {
|
||||
foreach ($keyVals as $keyVal) {
|
||||
$result[implode(',', $keyVal)] = null;
|
||||
}
|
||||
} else {
|
||||
$result = array_fill_keys($keyVals, null);
|
||||
}
|
||||
|
||||
$toFetch = array();
|
||||
|
||||
foreach ($keyVals as $keyVal) {
|
||||
|
||||
$kv = array_merge($otherCols, array($keyCol => $keyVal));
|
||||
if (is_array($keyCol)) {
|
||||
$kv = array_combine($keyCol, $keyVal);
|
||||
} else {
|
||||
$kv = array($keyCol => $keyVal);
|
||||
}
|
||||
|
||||
$kv = array_merge($otherCols, $kv);
|
||||
|
||||
$i = self::multicache($cls, $kv);
|
||||
|
||||
if ($i !== false) {
|
||||
$result[$keyVal] = $i;
|
||||
if (is_array($keyCol)) {
|
||||
$result[implode(',', $keyVal)] = $i;
|
||||
} else {
|
||||
$result[$keyVal] = $i;
|
||||
}
|
||||
} else if (!empty($keyVal)) {
|
||||
$toFetch[] = $keyVal;
|
||||
}
|
||||
@ -130,20 +146,43 @@ class Memcached_DataObject extends Safe_DataObject
|
||||
foreach ($otherCols as $otherKeyCol => $otherKeyVal) {
|
||||
$i->$otherKeyCol = $otherKeyVal;
|
||||
}
|
||||
$i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
|
||||
if (is_array($keyCol)) {
|
||||
$i->whereAdd(self::_inMultiKey($i, $keyCol, $toFetch));
|
||||
} else {
|
||||
$i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
|
||||
}
|
||||
if ($i->find()) {
|
||||
while ($i->fetch()) {
|
||||
$copy = clone($i);
|
||||
$copy->encache();
|
||||
$result[$i->$keyCol] = $copy;
|
||||
if (is_array($keyCol)) {
|
||||
$vals = array();
|
||||
foreach ($keyCol as $k) {
|
||||
$vals[] = $i->$k;
|
||||
}
|
||||
$result[implode(',', $vals)] = $copy;
|
||||
} else {
|
||||
$result[$i->$keyCol] = $copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save state of DB misses
|
||||
|
||||
foreach ($toFetch as $keyVal) {
|
||||
if (empty($result[$keyVal])) {
|
||||
$kv = array_merge($otherCols, array($keyCol => $keyVal));
|
||||
$r = null;
|
||||
if (is_array($keyCol)) {
|
||||
$r = $result[implode(',', $keyVal)];
|
||||
} else {
|
||||
$r = $result[$keyVal];
|
||||
}
|
||||
if (empty($r)) {
|
||||
if (is_array($keyCol)) {
|
||||
$kv = array_combine($keyCol, $keyVal);
|
||||
} else {
|
||||
$kv = array($keyCol => $keyVal);
|
||||
}
|
||||
$kv = array_merge($otherCols, $kv);
|
||||
// save the fact that no such row exists
|
||||
$c = self::memcache();
|
||||
if (!empty($c)) {
|
||||
@ -157,39 +196,129 @@ class Memcached_DataObject extends Safe_DataObject
|
||||
return $result;
|
||||
}
|
||||
|
||||
static function _inMultiKey($i, $cols, $values)
|
||||
{
|
||||
$types = array();
|
||||
|
||||
foreach ($cols as $col) {
|
||||
$types[$col] = $i->columnType($col);
|
||||
}
|
||||
|
||||
$first = true;
|
||||
|
||||
$query = '';
|
||||
|
||||
foreach ($values as $value) {
|
||||
if ($first) {
|
||||
$query .= '( ';
|
||||
$first = false;
|
||||
} else {
|
||||
$query .= ' OR ';
|
||||
}
|
||||
$query .= '( ';
|
||||
$i = 0;
|
||||
$firstc = true;
|
||||
foreach ($cols as $col) {
|
||||
if (!$firstc) {
|
||||
$query .= ' AND ';
|
||||
} else {
|
||||
$firstc = false;
|
||||
}
|
||||
switch ($types[$col]) {
|
||||
case 'string':
|
||||
case 'datetime':
|
||||
$query .= sprintf("%s = %s", $col, $i->_quote($value[$i]));
|
||||
break;
|
||||
default:
|
||||
$query .= sprintf("%s = %s", $col, $value[$i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$query .= ') ';
|
||||
}
|
||||
|
||||
if (!$first) {
|
||||
$query .= ' )';
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
static function pkeyCols($cls)
|
||||
{
|
||||
$i = DB_DataObject::factory($cls);
|
||||
if (empty($i)) {
|
||||
throw new Exception(_('Cannot instantiate a ' . $cls));
|
||||
}
|
||||
$types = $i->keyTypes();
|
||||
ksort($types);
|
||||
|
||||
$pkey = array();
|
||||
|
||||
foreach ($types as $key => $type) {
|
||||
if ($type == 'K' || $type == 'N') {
|
||||
$pkey[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
return $pkey;
|
||||
}
|
||||
|
||||
function listGet($cls, $keyCol, $keyVals)
|
||||
{
|
||||
$result = array_fill_keys($keyVals, array());
|
||||
$pkeyMap = array_fill_keys($keyVals, array());
|
||||
$results = array_fill_keys($keyVals, array());
|
||||
|
||||
$pkeyCols = self::pkeyCols($cls);
|
||||
|
||||
$toFetch = array();
|
||||
$allPkeys = array();
|
||||
|
||||
// We only cache keys -- not objects!
|
||||
|
||||
foreach ($keyVals as $keyVal) {
|
||||
$l = self::cacheGet(sprintf("%s:list:%s:%s", $cls, $keyCol, $keyVal));
|
||||
$l = self::cacheGet(sprintf("%s:list-ids:%s:%s", $cls, $keyCol, $keyVal));
|
||||
if ($l !== false) {
|
||||
$result[$keyVal] = $l;
|
||||
$pkeyMap[$keyVal] = $l;
|
||||
$allPkeys = array_merge($allPkeys, $l);
|
||||
} else {
|
||||
$toFetch[] = $keyVal;
|
||||
}
|
||||
}
|
||||
|
||||
$keyResults = self::pivotGet($cls, $pkeyCols, $allPkeys);
|
||||
|
||||
foreach ($pkeyMap as $keyVal => $pkeyList) {
|
||||
foreach ($pkeyList as $pkeyVal) {
|
||||
$i = $keyResults[$pkeyVal];
|
||||
if (!empty($i)) {
|
||||
$results[$keyVal][] = $i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($toFetch) > 0) {
|
||||
$i = DB_DataObject::factory($cls);
|
||||
if (empty($i)) {
|
||||
throw new Exception(_('Cannot instantiate class ' . $cls));
|
||||
}
|
||||
$i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
|
||||
if ($i->find()) {
|
||||
while ($i->fetch()) {
|
||||
$copy = clone($i);
|
||||
$copy->encache();
|
||||
$result[$i->$keyCol][] = $copy;
|
||||
}
|
||||
}
|
||||
foreach ($toFetch as $keyVal)
|
||||
{
|
||||
self::cacheSet(sprintf("%s:list:%s:%s", $cls, $keyCol, $keyVal),
|
||||
$result[$keyVal]);
|
||||
}
|
||||
$i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
|
||||
if ($i->find()) {
|
||||
while ($i->fetch()) {
|
||||
$copy = clone($i);
|
||||
$copy->encache();
|
||||
$result[$i->$keyCol][] = $copy;
|
||||
$pkeyVal = array();
|
||||
foreach ($pkeyCols as $pkeyCol) {
|
||||
$pkeyVal[] = $i->$pkeyCol;
|
||||
}
|
||||
$pkeyMap[$i->$keyCol][] = $pkeyVal;
|
||||
}
|
||||
}
|
||||
foreach ($toFetch as $keyVal) {
|
||||
self::cacheSet(sprintf("%s:list-ids:%s:%s", $cls, $keyCol, $keyVal),
|
||||
$pkeyMap[$keyVal]);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
Loading…
Reference in New Issue
Block a user