diff options
Diffstat (limited to 'classes')
-rw-r--r-- | classes/Notice.php | 164 | ||||
-rw-r--r-- | classes/User.php | 116 |
2 files changed, 214 insertions, 66 deletions
diff --git a/classes/Notice.php b/classes/Notice.php index b42a8726e..5bf8a2de8 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -24,6 +24,11 @@ if (!defined('LACONICA')) { exit(1); } */ require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; +/* We keep the first three 20-notice pages, plus one for pagination check, + * in the memcached cache. */ + +define('NOTICE_CACHE_WINDOW', 61); + class Notice extends Memcached_DataObject { ###START_AUTOCODE @@ -52,6 +57,12 @@ class Notice extends Memcached_DataObject return Profile::staticGet($this->profile_id); } + function delete() { + $this->blowCaches(); + $this->blowFavesCache(); + parent::delete(); + } + function saveTags() { /* extract all #hastags */ $count = preg_match_all('/(?:^|\s)#([A-Za-z0-9_\-\.]{1,64})/', strtolower($this->content), $match); @@ -118,11 +129,18 @@ class Notice extends Memcached_DataObject # XXX: someone clever could prepend instead of clearing the cache if (common_config('memcached', 'enabled')) { - $notice->blowSubsCache(); + $notice->blowCaches(); } return $notice; } + + function blowCaches() { + $this->blowSubsCache(); + $this->blowNoticeCache(); + $this->blowRepliesCache(); + $this->blowPublicCache(); + } function blowSubsCache() { $cache = common_memcache(); @@ -141,4 +159,148 @@ class Notice extends Memcached_DataObject unset($user); } } + + function blowNoticeCache() { + if ($this->is_local) { + $cache = common_memcache(); + if ($cache) { + $cache->delete(common_cache_key('user:notices:'.$this->profile_id)); + } + } + } + + function blowRepliesCache() { + $cache = common_memcache(); + if ($cache) { + $reply = new Reply(); + $reply->notice_id = $this->id; + if ($reply->find()) { + while ($reply->fetch()) { + $cache->delete(common_cache_key('user:replies:'.$reply->profile_id)); + } + } + $reply->free(); + unset($reply); + } + } + + function blowPublicCache() { + if ($this->is_local) { + $cache = common_memcache(); + if ($cache) { + $cache->delete(common_cache_key('public')); + } + } + } + + function blowFavesCache() { + $cache = common_memcache(); + if ($cache) { + $fave = new Fave(); + $fave->notice_id = $this->id; + if ($fave->find()) { + while ($fave->fetch()) { + $cache->delete(common_cache_key('user:faves:'.$fave->user_id)); + } + } + $fave->free(); + unset($fave); + } + } + + static function getStream($qry, $cachekey, $offset=0, $limit=20) { + + if (common_config('memcached', 'enabled')) { + return Notice::getCachedStream($qry, $cachekey, $offset, $limit); + } else { + return Notice::getStreamDirect($qry, $offset, $limit); + } + + } + + static function getStreamDirect($qry, $offset, $limit) { + + $qry .= 'ORDER BY notice.created DESC, notice.id DESC '; + + if(common_config('db','type')=='pgsql') { + $qry .= 'LIMIT ' . $limit . ' OFFSET ' . $offset; + } else { + $qry .= 'LIMIT ' . $offset . ', ' . $limit; + } + + $notice = new Notice(); + + $notice->query($qry); + + return $notice; + } + + static function getCachedStream($qry, $cachekey, $offset, $limit) { + + # If outside our cache window, just go to the DB + + if ($offset + $limit > NOTICE_CACHE_WINDOW) { + return Notice::getStreamDirect($qry, $offset, $limit); + } + + # Get the cache; if we can't, just go to the DB + + $cache = common_memcache(); + + if (!$cache) { + return Notice::getStreamDirect($qry, $offset, $limit); + } + + # Get the notices out of the cache + + $notices = $cache->get(common_cache_key($cachekey)); + + # On a cache hit, return a DB-object-like wrapper + + if ($notices) { + $wrapper = new NoticeWrapper(array_slice($notices, $offset, $limit)); + return $wrapper; + } + + # Otherwise, get the full cache window out of the DB + + $notice = Notice::getStreamDirect($qry, 0, NOTICE_CACHE_WINDOW); + + # If there are no hits, just return the value + + if (!$notice) { + return $notice; + } + + # Pack results into an array + + $notices = array(); + + while ($notice->fetch()) { + $notices[] = clone($notice); + } + + # Store the array in the cache for next time + + $cache->set(common_cache_key($cachekey), $notices); + + # return a wrapper of the array for use now + + $wrapper = new NoticeWrapper(array_slice($notices, $offset, $limit)); + return $wrapper; + } + + function publicStream($page) { + + $qry = 'SELECT * FROM notice '; + + if (common_config('public', 'localonly')) { + $qry .= ' WHERE is_local = 1 '; + } + + return Notice::getStream($qry, + 'public', + ($page-1)*NOTICES_PER_PAGE, + NOTICES_PER_PAGE + 1); + } } diff --git a/classes/User.php b/classes/User.php index de260035a..b8af0d0a6 100644 --- a/classes/User.php +++ b/classes/User.php @@ -19,11 +19,6 @@ if (!defined('LACONICA')) { exit(1); } -/* We keep the first three 20-notice pages, plus one for pagination check, - * in the memcached cache. */ - -define('WITHFRIENDS_CACHE_WINDOW', 61); - /** * Table Definition for user */ @@ -153,60 +148,8 @@ class User extends Memcached_DataObject return true; } - function noticesWithFriends($offset=0, $limit=20) { - - # We clearly need a more elegant way to make this work. - - if (common_config('memcached', 'enabled')) { - if ($offset + $limit <= WITHFRIENDS_CACHE_WINDOW) { - $cached = $this->noticesWithFriendsWindow(); - $wrapper = new NoticeWrapper(array_slice($cached, $offset, $limit)); - return $wrapper; - } - } - - $notice = new Notice(); - - $query='SELECT notice.* ' . - 'FROM notice JOIN subscription on notice.profile_id = subscription.subscribed ' . - 'WHERE subscription.subscriber = ' . $this->id . ' ' . - 'ORDER BY created DESC, notice.id DESC '; - if(common_config('db','type')=='pgsql') { - $query=$query . 'LIMIT ' . $limit . ' OFFSET ' . $offset; - } else { - $query=$query . 'LIMIT ' . $offset . ', ' . $limit; - } - $notice->query($query); - - return $notice; - } - - function favoriteNotices($offset=0, $limit=20) { - - $notice = new Notice(); - - $notice->query('SELECT notice.* ' . - 'FROM notice JOIN fave on notice.id = fave.notice_id ' . - 'WHERE fave.user_id = ' . $this->id . ' ' . - 'ORDER BY notice.created DESC, notice.id DESC ' . - 'LIMIT ' . $offset . ', ' . $limit); - - return $notice; - } - function noticesWithFriendsWindow() { - $cache = common_memcache(); - - if (!$cache) { - return NULL; - } - - $notices = $cache->get(common_cache_key('user:notices_with_friends:' . $this->id)); - - if ($notices) { - return $notices; - } $notice = new Notice(); @@ -216,14 +159,6 @@ class User extends Memcached_DataObject 'ORDER BY created DESC, notice.id DESC ' . 'LIMIT 0, ' . WITHFRIENDS_CACHE_WINDOW); - $notices = array(); - - while ($notice->fetch()) { - $notices[] = clone($notice); - } - - $cache->set(common_cache_key('user:notices_with_friends:' . $this->id), $notices); - return $notices; } static function register($fields) { @@ -383,4 +318,55 @@ class User extends Memcached_DataObject return $user; } + + function getReplies($offset=0, $limit=NOTICES_PER_PAGE) { + $qry = + 'SELECT notice.* ' . + 'FROM notice JOIN reply ON notice.id = reply.notice_id ' . + 'WHERE reply.profile_id = %d '; + + return Notice::getStream(sprintf($qry, $this->id), + 'user:replies:'.$this->id, + $offset, $limit); + } + + function getNotices($offset=0, $limit=NOTICES_PER_PAGE) { + $qry = + 'SELECT * ' . + 'FROM notice ' . + 'WHERE profile_id = %d '; + + return Notice::getStream(sprintf($qry, $this->id), + 'user:notices:'.$this->id, + $offset, $limit); + } + + function favoriteNotices($offset=0, $limit=NOTICES_PER_PAGE) { + $qry = + 'SELECT notice.* ' . + 'FROM notice JOIN fave ON notice.id = fave.notice_id ' . + 'WHERE fave.profile_id = %d '; + + return Notice::getStream(sprintf($qry, $this->id), + 'user:faves:'.$this->id, + $offset, $limit); + } + + function noticesWithFriends($offset=0, $limit=NOTICES_PER_PAGE) { + $qry = + 'SELECT notice.* ' . + 'FROM notice JOIN subscription ON notice.profile_id = subscription.subscribed ' . + 'WHERE subscription.subscriber = %d'; + + return Notice::getStream(sprintf($qry, $this->id), + 'user:notices_with_friends:' . $this->id, + $offset, $limit); + } + + function blowFavesCache() { + $cache = common_memcache(); + if ($cache) { + $cache->delete(common_cache_key('user:faves:'.$this->id)); + } + } } |