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__);
|
common_log_db_error($fave, 'INSERT', __FILE__);
|
||||||
return false;
|
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));
|
Event::handle('EndFavorNotice', array($profile, $notice));
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ class Fave extends Memcached_DataObject
|
|||||||
if (Event::handle('StartDisfavorNotice', array($profile, $notice, &$result))) {
|
if (Event::handle('StartDisfavorNotice', array($profile, $notice, &$result))) {
|
||||||
|
|
||||||
$result = parent::delete();
|
$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) {
|
if ($result) {
|
||||||
Event::handle('EndDisfavorNotice', array($profile, $notice));
|
Event::handle('EndDisfavorNotice', array($profile, $notice));
|
||||||
|
@ -105,23 +105,39 @@ class Memcached_DataObject extends Safe_DataObject
|
|||||||
*/
|
*/
|
||||||
static function pivotGet($cls, $keyCol, $keyVals, $otherCols = array())
|
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();
|
$toFetch = array();
|
||||||
|
|
||||||
foreach ($keyVals as $keyVal) {
|
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);
|
$i = self::multicache($cls, $kv);
|
||||||
|
|
||||||
if ($i !== false) {
|
if ($i !== false) {
|
||||||
$result[$keyVal] = $i;
|
if (is_array($keyCol)) {
|
||||||
|
$result[implode(',', $keyVal)] = $i;
|
||||||
|
} else {
|
||||||
|
$result[$keyVal] = $i;
|
||||||
|
}
|
||||||
} else if (!empty($keyVal)) {
|
} else if (!empty($keyVal)) {
|
||||||
$toFetch[] = $keyVal;
|
$toFetch[] = $keyVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($toFetch) > 0) {
|
if (count($toFetch) > 0) {
|
||||||
$i = DB_DataObject::factory($cls);
|
$i = DB_DataObject::factory($cls);
|
||||||
if (empty($i)) {
|
if (empty($i)) {
|
||||||
@ -130,20 +146,43 @@ class Memcached_DataObject extends Safe_DataObject
|
|||||||
foreach ($otherCols as $otherKeyCol => $otherKeyVal) {
|
foreach ($otherCols as $otherKeyCol => $otherKeyVal) {
|
||||||
$i->$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()) {
|
if ($i->find()) {
|
||||||
while ($i->fetch()) {
|
while ($i->fetch()) {
|
||||||
$copy = clone($i);
|
$copy = clone($i);
|
||||||
$copy->encache();
|
$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
|
// Save state of DB misses
|
||||||
|
|
||||||
foreach ($toFetch as $keyVal) {
|
foreach ($toFetch as $keyVal) {
|
||||||
if (empty($result[$keyVal])) {
|
$r = null;
|
||||||
$kv = array_merge($otherCols, array($keyCol => $keyVal));
|
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
|
// save the fact that no such row exists
|
||||||
$c = self::memcache();
|
$c = self::memcache();
|
||||||
if (!empty($c)) {
|
if (!empty($c)) {
|
||||||
@ -153,43 +192,133 @@ class Memcached_DataObject extends Safe_DataObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
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)
|
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();
|
$toFetch = array();
|
||||||
|
$allPkeys = array();
|
||||||
|
|
||||||
|
// We only cache keys -- not objects!
|
||||||
|
|
||||||
foreach ($keyVals as $keyVal) {
|
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) {
|
if ($l !== false) {
|
||||||
$result[$keyVal] = $l;
|
$pkeyMap[$keyVal] = $l;
|
||||||
|
$allPkeys = array_merge($allPkeys, $l);
|
||||||
} else {
|
} else {
|
||||||
$toFetch[] = $keyVal;
|
$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) {
|
if (count($toFetch) > 0) {
|
||||||
$i = DB_DataObject::factory($cls);
|
$i = DB_DataObject::factory($cls);
|
||||||
if (empty($i)) {
|
if (empty($i)) {
|
||||||
throw new Exception(_('Cannot instantiate class ' . $cls));
|
throw new Exception(_('Cannot instantiate class ' . $cls));
|
||||||
}
|
}
|
||||||
$i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
|
$i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
|
||||||
if ($i->find()) {
|
if ($i->find()) {
|
||||||
while ($i->fetch()) {
|
while ($i->fetch()) {
|
||||||
$copy = clone($i);
|
$copy = clone($i);
|
||||||
$copy->encache();
|
$copy->encache();
|
||||||
$result[$i->$keyCol][] = $copy;
|
$result[$i->$keyCol][] = $copy;
|
||||||
}
|
$pkeyVal = array();
|
||||||
}
|
foreach ($pkeyCols as $pkeyCol) {
|
||||||
foreach ($toFetch as $keyVal)
|
$pkeyVal[] = $i->$pkeyCol;
|
||||||
{
|
}
|
||||||
self::cacheSet(sprintf("%s:list:%s:%s", $cls, $keyCol, $keyVal),
|
$pkeyMap[$i->$keyCol][] = $pkeyVal;
|
||||||
$result[$keyVal]);
|
}
|
||||||
}
|
}
|
||||||
|
foreach ($toFetch as $keyVal) {
|
||||||
|
self::cacheSet(sprintf("%s:list-ids:%s:%s", $cls, $keyCol, $keyVal),
|
||||||
|
$pkeyMap[$keyVal]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
Loading…
Reference in New Issue
Block a user