summaryrefslogtreecommitdiff
path: root/classes
diff options
context:
space:
mode:
Diffstat (limited to 'classes')
-rw-r--r--classes/Fave.php53
-rw-r--r--classes/Foreign_link.php2
-rw-r--r--classes/Notice.php241
-rw-r--r--classes/Notice_inbox.php51
-rw-r--r--classes/Notice_tag.php61
-rw-r--r--classes/Profile.php53
-rw-r--r--classes/Reply.php47
-rw-r--r--classes/User.php68
-rwxr-xr-xclasses/User_group.php53
-rwxr-xr-xclasses/laconica.ini2
10 files changed, 517 insertions, 114 deletions
diff --git a/classes/Fave.php b/classes/Fave.php
index 24df5938c..915b4572f 100644
--- a/classes/Fave.php
+++ b/classes/Fave.php
@@ -4,7 +4,7 @@
*/
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
-class Fave extends Memcached_DataObject
+class Fave extends Memcached_DataObject
{
###START_AUTOCODE
/* the code below is auto generated do not remove the above tag */
@@ -31,9 +31,58 @@ class Fave extends Memcached_DataObject
}
return $fave;
}
-
+
function &pkeyGet($kv)
{
return Memcached_DataObject::pkeyGet('Fave', $kv);
}
+
+ function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE)
+ {
+ $ids = Notice::stream(array('Fave', '_streamDirect'),
+ array($user_id),
+ 'fave:ids_by_user:'.$user_id,
+ $offset, $limit);
+ return $ids;
+ }
+
+ function _streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since)
+ {
+ $fav = new Fave();
+
+ $fav->user_id = $user_id;
+
+ $fav->selectAdd();
+ $fav->selectAdd('notice_id');
+
+ if ($since_id != 0) {
+ $fav->whereAdd('notice_id > ' . $since_id);
+ }
+
+ if ($before_id != 0) {
+ $fav->whereAdd('notice_id < ' . $before_id);
+ }
+
+ if (!is_null($since)) {
+ $fav->whereAdd('modified > \'' . date('Y-m-d H:i:s', $since) . '\'');
+ }
+
+ // NOTE: we sort by fave time, not by notice time!
+
+ $fav->orderBy('modified DESC');
+
+ if (!is_null($offset)) {
+ $fav->limit($offset, $limit);
+ }
+
+ $ids = array();
+
+ if ($fav->find()) {
+ while ($fav->fetch()) {
+ $ids[] = $fav->notice_id;
+ }
+ }
+
+ return $ids;
+ }
}
diff --git a/classes/Foreign_link.php b/classes/Foreign_link.php
index afc0e2180..af2b3f189 100644
--- a/classes/Foreign_link.php
+++ b/classes/Foreign_link.php
@@ -17,6 +17,8 @@ class Foreign_link extends Memcached_DataObject
public $noticesync; // tinyint(1) not_null default_1
public $friendsync; // tinyint(1) not_null default_2
public $profilesync; // tinyint(1) not_null default_1
+ public $last_noticesync; // datetime()
+ public $last_friendsync; // datetime()
public $created; // datetime() not_null
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
diff --git a/classes/Notice.php b/classes/Notice.php
index 5fa0d79a1..771a4e715 100644
--- a/classes/Notice.php
+++ b/classes/Notice.php
@@ -197,7 +197,12 @@ class Notice extends Memcached_DataObject
$notice->saveTags();
$notice->saveGroups();
- $notice->addToInboxes();
+ if (common_config('queue', 'enabled')) {
+ $notice->addToAuthorInbox();
+ } else {
+ $notice->addToInboxes();
+ }
+
$notice->query('COMMIT');
Event::handle('EndNoticeSave', array($notice));
@@ -207,7 +212,11 @@ class Notice extends Memcached_DataObject
# XXX: someone clever could prepend instead of clearing the cache
if (common_config('memcached', 'enabled')) {
- $notice->blowCaches();
+ if (common_config('queue', 'enabled')) {
+ $notice->blowAuthorCaches();
+ } else {
+ $notice->blowCaches();
+ }
}
return $notice;
@@ -271,6 +280,17 @@ class Notice extends Memcached_DataObject
$this->blowGroupCache($blowLast);
}
+ function blowAuthorCaches($blowLast=false)
+ {
+ // Clear the user's cache
+ $cache = common_memcache();
+ if (!empty($cache)) {
+ $cache->delete(common_cache_key('notice_inbox:by_user:'.$this->profile_id));
+ }
+ $this->blowNoticeCache($blowLast);
+ $this->blowPublicCache($blowLast);
+ }
+
function blowGroupCache($blowLast=false)
{
$cache = common_memcache();
@@ -279,17 +299,17 @@ class Notice extends Memcached_DataObject
$group_inbox->notice_id = $this->id;
if ($group_inbox->find()) {
while ($group_inbox->fetch()) {
- $cache->delete(common_cache_key('group:notices:'.$group_inbox->group_id));
+ $cache->delete(common_cache_key('user_group:notice_ids:' . $group_inbox->group_id));
if ($blowLast) {
- $cache->delete(common_cache_key('group:notices:'.$group_inbox->group_id.';last'));
+ $cache->delete(common_cache_key('user_group:notice_ids:' . $group_inbox->group_id.';last'));
}
$member = new Group_member();
$member->group_id = $group_inbox->group_id;
if ($member->find()) {
while ($member->fetch()) {
- $cache->delete(common_cache_key('user:notices_with_friends:' . $member->profile_id));
+ $cache->delete(common_cache_key('notice_inbox:by_user:' . $member->profile_id));
if ($blowLast) {
- $cache->delete(common_cache_key('user:notices_with_friends:' . $member->profile_id . ';last'));
+ $cache->delete(common_cache_key('notice_inbox:by_user:' . $member->profile_id . ';last'));
}
}
}
@@ -308,10 +328,7 @@ class Notice extends Memcached_DataObject
$tag->notice_id = $this->id;
if ($tag->find()) {
while ($tag->fetch()) {
- $cache->delete(common_cache_key('notice_tag:notice_stream:' . $tag->tag));
- if ($blowLast) {
- $cache->delete(common_cache_key('notice_tag:notice_stream:' . $tag->tag . ';last'));
- }
+ $tag->blowCache($blowLast);
}
}
$tag->free();
@@ -332,9 +349,9 @@ class Notice extends Memcached_DataObject
'WHERE subscription.subscribed = ' . $this->profile_id);
while ($user->fetch()) {
- $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id));
+ $cache->delete(common_cache_key('notice_inbox:by_user:'.$user->id));
if ($blowLast) {
- $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id . ';last'));
+ $cache->delete(common_cache_key('notice_inbox:by_user:'.$user->id.';last'));
}
}
$user->free();
@@ -346,10 +363,10 @@ class Notice extends Memcached_DataObject
{
if ($this->is_local) {
$cache = common_memcache();
- if ($cache) {
- $cache->delete(common_cache_key('profile:notices:'.$this->profile_id));
+ if (!empty($cache)) {
+ $cache->delete(common_cache_key('profile:notice_ids:'.$this->profile_id));
if ($blowLast) {
- $cache->delete(common_cache_key('profile:notices:'.$this->profile_id.';last'));
+ $cache->delete(common_cache_key('profile:notice_ids:'.$this->profile_id.';last'));
}
}
}
@@ -363,9 +380,9 @@ class Notice extends Memcached_DataObject
$reply->notice_id = $this->id;
if ($reply->find()) {
while ($reply->fetch()) {
- $cache->delete(common_cache_key('user:replies:'.$reply->profile_id));
+ $cache->delete(common_cache_key('reply:stream:'.$reply->profile_id));
if ($blowLast) {
- $cache->delete(common_cache_key('user:replies:'.$reply->profile_id.';last'));
+ $cache->delete(common_cache_key('reply:stream:'.$reply->profile_id.';last'));
}
}
}
@@ -395,9 +412,9 @@ class Notice extends Memcached_DataObject
$fave->notice_id = $this->id;
if ($fave->find()) {
while ($fave->fetch()) {
- $cache->delete(common_cache_key('user:faves:'.$fave->user_id));
+ $cache->delete(common_cache_key('fave:ids_by_user:'.$fave->user_id));
if ($blowLast) {
- $cache->delete(common_cache_key('user:faves:'.$fave->user_id.';last'));
+ $cache->delete(common_cache_key('fave:ids_by_user:'.$fave->user_id.';last'));
}
}
}
@@ -593,27 +610,80 @@ class Notice extends Memcached_DataObject
return $wrapper;
}
+ function getStreamByIds($ids)
+ {
+ $cache = common_memcache();
+
+ if (!empty($cache)) {
+ $notices = array();
+ foreach ($ids as $id) {
+ $notices[] = Notice::staticGet('id', $id);
+ }
+ return new ArrayWrapper($notices);
+ } else {
+ $notice = new Notice();
+ $notice->whereAdd('id in (' . implode(', ', $ids) . ')');
+ $notice->orderBy('id DESC');
+
+ $notice->find();
+ return $notice;
+ }
+ }
+
function publicStream($offset=0, $limit=20, $since_id=0, $before_id=0, $since=null)
{
+ $ids = Notice::stream(array('Notice', '_publicStreamDirect'),
+ array(),
+ 'public',
+ $offset, $limit, $since_id, $before_id, $since);
+
+ return Notice::getStreamByIds($ids);
+ }
+
+ function _publicStreamDirect($offset=0, $limit=20, $since_id=0, $before_id=0, $since=null)
+ {
+ $notice = new Notice();
+
+ $notice->selectAdd(); // clears it
+ $notice->selectAdd('id');
- $parts = array();
+ $notice->orderBy('id DESC');
- $qry = 'SELECT * FROM notice ';
+ if (!is_null($offset)) {
+ $notice->limit($offset, $limit);
+ }
if (common_config('public', 'localonly')) {
- $parts[] = 'is_local = 1';
+ $notice->whereAdd('is_local = 1');
} else {
# -1 == blacklisted
- $parts[] = 'is_local != -1';
+ $notice->whereAdd('is_local != -1');
}
- if ($parts) {
- $qry .= ' WHERE ' . implode(' AND ', $parts);
+ if ($since_id != 0) {
+ $notice->whereAdd('id > ' . $since_id);
}
- return Notice::getStream($qry,
- 'public',
- $offset, $limit, $since_id, $before_id, null, $since);
+ if ($before_id != 0) {
+ $notice->whereAdd('id < ' . $before_id);
+ }
+
+ if (!is_null($since)) {
+ $notice->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\'');
+ }
+
+ $ids = array();
+
+ if ($notice->find()) {
+ while ($notice->fetch()) {
+ $ids[] = $notice->id;
+ }
+ }
+
+ $notice->free();
+ $notice = NULL;
+
+ return $ids;
}
function addToInboxes()
@@ -639,6 +709,33 @@ class Notice extends Memcached_DataObject
return;
}
+ function addToAuthorInbox()
+ {
+ $enabled = common_config('inboxes', 'enabled');
+
+ if ($enabled === true || $enabled === 'transitional') {
+ $user = User::staticGet('id', $this->profile_id);
+ if (empty($user)) {
+ return;
+ }
+ $inbox = new Notice_inbox();
+ $UT = common_config('db','type')=='pgsql'?'"user"':'user';
+ $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created) ' .
+ "SELECT $UT.id, " . $this->id . ", '" . $this->created . "' " .
+ "FROM $UT " .
+ "WHERE $UT.id = " . $this->profile_id . ' ' .
+ 'AND NOT EXISTS (SELECT user_id, notice_id ' .
+ 'FROM notice_inbox ' .
+ "WHERE user_id = " . $this->profile_id . ' '.
+ 'AND notice_id = ' . $this->id . ' )';
+ if ($enabled === 'transitional') {
+ $qry .= " AND $UT.inboxed = 1";
+ }
+ $inbox->query($qry);
+ }
+ return;
+ }
+
function saveGroups()
{
$enabled = common_config('inboxes', 'enabled');
@@ -691,24 +788,29 @@ class Notice extends Memcached_DataObject
// FIXME: do this in an offline daemon
- $inbox = new Notice_inbox();
- $UT = common_config('db','type')=='pgsql'?'"user"':'user';
- $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created, source) ' .
- "SELECT $UT.id, " . $this->id . ", '" . $this->created . "', 2 " .
- "FROM $UT JOIN group_member ON $UT.id = group_member.profile_id " .
- 'WHERE group_member.group_id = ' . $group->id . ' ' .
- 'AND NOT EXISTS (SELECT user_id, notice_id ' .
- 'FROM notice_inbox ' .
- "WHERE user_id = $UT.id " .
- 'AND notice_id = ' . $this->id . ' )';
- if ($enabled === 'transitional') {
- $qry .= " AND $UT.inboxed = 1";
- }
- $result = $inbox->query($qry);
+ $this->addToGroupInboxes($group);
}
}
}
+ function addToGroupInboxes($group)
+ {
+ $inbox = new Notice_inbox();
+ $UT = common_config('db','type')=='pgsql'?'"user"':'user';
+ $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created, source) ' .
+ "SELECT $UT.id, " . $this->id . ", '" . $this->created . "', 2 " .
+ "FROM $UT JOIN group_member ON $UT.id = group_member.profile_id " .
+ 'WHERE group_member.group_id = ' . $group->id . ' ' .
+ 'AND NOT EXISTS (SELECT user_id, notice_id ' .
+ 'FROM notice_inbox ' .
+ "WHERE user_id = $UT.id " .
+ 'AND notice_id = ' . $this->id . ' )';
+ if ($enabled === 'transitional') {
+ $qry .= " AND $UT.inboxed = 1";
+ }
+ $result = $inbox->query($qry);
+ }
+
function saveReplies()
{
// Alternative reply format
@@ -895,4 +997,59 @@ class Notice extends Memcached_DataObject
array('notice' => $this->id));
}
}
+
+ function stream($fn, $args, $cachekey, $offset=0, $limit=20, $since_id=0, $before_id=0, $since=null)
+ {
+ $cache = common_memcache();
+
+ if (empty($cache) ||
+ $since_id != 0 || $before_id != 0 || !is_null($since) ||
+ ($offset + $limit) > NOTICE_CACHE_WINDOW) {
+ return call_user_func_array($fn, array_merge($args, array($offset, $limit, $since_id,
+ $before_id, $since)));
+ }
+
+ $idkey = common_cache_key($cachekey);
+
+ $idstr = $cache->get($idkey);
+
+ if (!empty($idstr)) {
+ // Cache hit! Woohoo!
+ $window = explode(',', $idstr);
+ $ids = array_slice($window, $offset, $limit);
+ return $ids;
+ }
+
+ $laststr = $cache->get($idkey.';last');
+
+ if (!empty($laststr)) {
+ $window = explode(',', $laststr);
+ $last_id = $window[0];
+ $new_ids = call_user_func_array($fn, array_merge($args, array(0, NOTICE_CACHE_WINDOW,
+ $last_id, 0, null)));
+
+ $new_window = array_merge($new_ids, $window);
+
+ $new_windowstr = implode(',', $new_window);
+
+ $result = $cache->set($idkey, $new_windowstr);
+ $result = $cache->set($idkey . ';last', $new_windowstr);
+
+ $ids = array_slice($new_window, $offset, $limit);
+
+ return $ids;
+ }
+
+ $window = call_user_func_array($fn, array_merge($args, array(0, NOTICE_CACHE_WINDOW,
+ 0, 0, null)));
+
+ $windowstr = implode(',', $window);
+
+ $result = $cache->set($idkey, $windowstr);
+ $result = $cache->set($idkey . ';last', $windowstr);
+
+ $ids = array_slice($window, $offset, $limit);
+
+ return $ids;
+ }
}
diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php
index 81ddb4538..dec14b0d1 100644
--- a/classes/Notice_inbox.php
+++ b/classes/Notice_inbox.php
@@ -1,7 +1,7 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, Controlez-Vous, Inc.
+ * Copyright (C) 2008, 2009, Control Yourself, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -21,7 +21,11 @@ if (!defined('LACONICA')) { exit(1); }
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
-class Notice_inbox extends Memcached_DataObject
+// We keep 5 pages of inbox notices in memcache, +1 for pagination check
+
+define('INBOX_CACHE_WINDOW', 101);
+
+class Notice_inbox extends Memcached_DataObject
{
###START_AUTOCODE
/* the code below is auto generated do not remove the above tag */
@@ -38,4 +42,47 @@ class Notice_inbox extends Memcached_DataObject
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
+
+ function stream($user_id, $offset, $limit, $since_id, $before_id, $since)
+ {
+ return Notice::stream(array('Notice_inbox', '_streamDirect'),
+ array($user_id),
+ 'notice_inbox:by_user:'.$user_id,
+ $offset, $limit, $since_id, $before_id, $since);
+ }
+
+ function _streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since)
+ {
+ $inbox = new Notice_inbox();
+
+ $inbox->user_id = $user_id;
+
+ if ($since_id != 0) {
+ $inbox->whereAdd('notice_id > ' . $since_id);
+ }
+
+ if ($before_id != 0) {
+ $inbox->whereAdd('notice_id < ' . $before_id);
+ }
+
+ if (!is_null($since)) {
+ $inbox->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\'');
+ }
+
+ $inbox->orderBy('notice_id DESC');
+
+ if (!is_null($offset)) {
+ $inbox->limit($offset, $limit);
+ }
+
+ $ids = array();
+
+ if ($inbox->find()) {
+ while ($inbox->fetch()) {
+ $ids[] = $inbox->notice_id;
+ }
+ }
+
+ return $ids;
+ }
}
diff --git a/classes/Notice_tag.php b/classes/Notice_tag.php
index f2247299a..e5b772243 100644
--- a/classes/Notice_tag.php
+++ b/classes/Notice_tag.php
@@ -37,21 +37,62 @@ class Notice_tag extends Memcached_DataObject
###END_AUTOCODE
static function getStream($tag, $offset=0, $limit=20) {
- $qry =
- 'SELECT notice.* ' .
- 'FROM notice JOIN notice_tag ON notice.id = notice_tag.notice_id ' .
- "WHERE notice_tag.tag = '%s' ";
-
- return Notice::getStream(sprintf($qry, $tag),
- 'notice_tag:notice_stream:' . common_keyize($tag),
- $offset, $limit);
+
+ $ids = Notice::stream(array('Notice_tag', '_streamDirect'),
+ array($tag),
+ 'notice_tag:notice_ids:' . common_keyize($tag),
+ $offset, $limit);
+
+ return Notice::getStreamByIds($ids);
+ }
+
+ function _streamDirect($tag, $offset, $limit, $since_id, $before_id, $since)
+ {
+ $nt = new Notice_tag();
+
+ $nt->tag = $tag;
+
+ $nt->selectAdd();
+ $nt->selectAdd('notice_id');
+
+ if ($since_id != 0) {
+ $nt->whereAdd('notice_id > ' . $since_id);
+ }
+
+ if ($before_id != 0) {
+ $nt->whereAdd('notice_id < ' . $before_id);
+ }
+
+ if (!is_null($since)) {
+ $nt->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\'');
+ }
+
+ $nt->orderBy('notice_id DESC');
+
+ if (!is_null($offset)) {
+ $nt->limit($offset, $limit);
+ }
+
+ $ids = array();
+
+ if ($nt->find()) {
+ while ($nt->fetch()) {
+ $ids[] = $nt->notice_id;
+ }
+ }
+
+ return $ids;
}
- function blowCache()
+ function blowCache($blowLast=false)
{
$cache = common_memcache();
if ($cache) {
- $cache->delete(common_cache_key('notice_tag:notice_stream:' . $this->tag));
+ $idkey = common_cache_key('notice_tag:notice_ids:' . common_keyize($this->tag));
+ $cache->delete($idkey);
+ if ($blowLast) {
+ $cache->delete($idkey.';last');
+ }
}
}
diff --git a/classes/Profile.php b/classes/Profile.php
index f3bfe299c..ae5641d79 100644
--- a/classes/Profile.php
+++ b/classes/Profile.php
@@ -155,14 +155,51 @@ class Profile extends Memcached_DataObject
function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0)
{
- $qry =
- 'SELECT * ' .
- 'FROM notice ' .
- 'WHERE profile_id = %d ';
-
- return Notice::getStream(sprintf($qry, $this->id),
- 'profile:notices:'.$this->id,
- $offset, $limit, $since_id, $before_id);
+ // XXX: I'm not sure this is going to be any faster. It probably isn't.
+ $ids = Notice::stream(array($this, '_streamDirect'),
+ array(),
+ 'profile:notice_ids:' . $this->id,
+ $offset, $limit, $since_id, $before_id);
+
+ return Notice::getStreamByIds($ids);
+ }
+
+ function _streamDirect($offset, $limit, $since_id, $before_id, $since)
+ {
+ $notice = new Notice();
+
+ $notice->profile_id = $this->id;
+
+ $notice->selectAdd();
+ $notice->selectAdd('id');
+
+ if ($since_id != 0) {
+ $notice->whereAdd('id > ' . $since_id);
+ }
+
+ if ($before_id != 0) {
+ $notice->whereAdd('id < ' . $before_id);
+ }
+
+ if (!is_null($since)) {
+ $notice->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\'');
+ }
+
+ $notice->orderBy('id DESC');
+
+ if (!is_null($offset)) {
+ $notice->limit($offset, $limit);
+ }
+
+ $ids = array();
+
+ if ($notice->find()) {
+ while ($notice->fetch()) {
+ $ids[] = $notice->id;
+ }
+ }
+
+ return $ids;
}
function isMember($group)
diff --git a/classes/Reply.php b/classes/Reply.php
index af86aaf87..4439053b4 100644
--- a/classes/Reply.php
+++ b/classes/Reply.php
@@ -4,7 +4,7 @@
*/
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
-class Reply extends Memcached_DataObject
+class Reply extends Memcached_DataObject
{
###START_AUTOCODE
/* the code below is auto generated do not remove the above tag */
@@ -13,7 +13,7 @@ class Reply extends Memcached_DataObject
public $notice_id; // int(4) primary_key not_null
public $profile_id; // int(4) primary_key not_null
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
- public $replied_id; // int(4)
+ public $replied_id; // int(4)
/* Static get */
function staticGet($k,$v=null)
@@ -21,4 +21,47 @@ class Reply extends Memcached_DataObject
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
+
+ function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
+ {
+ $ids = Notice::stream(array('Reply', '_streamDirect'),
+ array($user_id),
+ 'reply:stream:' . $user_id,
+ $offset, $limit, $since_id, $before_id, $since);
+ return $ids;
+ }
+
+ function _streamDirect($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
+ {
+ $reply = new Reply();
+ $reply->profile_id = $user_id;
+
+ if ($since_id != 0) {
+ $reply->whereAdd('notice_id > ' . $since_id);
+ }
+
+ if ($before_id != 0) {
+ $reply->whereAdd('notice_id < ' . $before_id);
+ }
+
+ if (!is_null($since)) {
+ $reply->whereAdd('modified > \'' . date('Y-m-d H:i:s', $since) . '\'');
+ }
+
+ $reply->orderBy('notice_id DESC');
+
+ if (!is_null($offset)) {
+ $reply->limit($offset, $limit);
+ }
+
+ $ids = array();
+
+ if ($reply->find()) {
+ while ($reply->fetch()) {
+ $ids[] = $reply->notice_id;
+ }
+ }
+
+ return $ids;
+ }
}
diff --git a/classes/User.php b/classes/User.php
index 3b9b5cd83..b5ac7b220 100644
--- a/classes/User.php
+++ b/classes/User.php
@@ -349,30 +349,31 @@ class User extends Memcached_DataObject
$cache = common_memcache();
// XXX: Kind of a hack.
+
if ($cache) {
// This is the stream of favorite notices, in rev chron
// order. This forces it into cache.
- $faves = $this->favoriteNotices(0, NOTICE_CACHE_WINDOW);
- $cnt = 0;
- while ($faves->fetch()) {
- if ($faves->id < $notice->id) {
- // If we passed it, it's not a fave
- return false;
- } else if ($faves->id == $notice->id) {
- // If it matches a cached notice, then it's a fave
- return true;
- }
- $cnt++;
+
+ $ids = Fave::stream($this->id, 0, NOTICE_CACHE_WINDOW);
+
+ // If it's in the list, then it's a fave
+
+ if (in_array($notice->id, $ids)) {
+ return true;
}
+
// If we're not past the end of the cache window,
// then the cache has all available faves, so this one
// is not a fave.
- if ($cnt < NOTICE_CACHE_WINDOW) {
+
+ if (count($ids) < NOTICE_CACHE_WINDOW) {
return false;
}
+
// Otherwise, cache doesn't have all faves;
// fall through to the default
}
+
$fave = Fave::pkeyGet(array('user_id' => $this->id,
'notice_id' => $notice->id));
return ((is_null($fave)) ? false : true);
@@ -401,13 +402,9 @@ class User extends Memcached_DataObject
function getReplies($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
{
- $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, $since_id, $before_id, null, $since);
+ $ids = Reply::stream($this->id, $offset, $limit, $since_id, $before_id, $since);
+ common_debug("Ids = " . implode(',', $ids));
+ return Notice::getStreamByIds($ids);
}
function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
@@ -422,13 +419,8 @@ class User extends Memcached_DataObject
function favoriteNotices($offset=0, $limit=NOTICES_PER_PAGE)
{
- $qry =
- 'SELECT notice.* ' .
- 'FROM notice JOIN fave ON notice.id = fave.notice_id ' .
- 'WHERE fave.user_id = %d ';
- return Notice::getStream(sprintf($qry, $this->id),
- 'user:faves:'.$this->id,
- $offset, $limit);
+ $ids = Fave::stream($this->id, $offset, $limit);
+ return Notice::getStreamByIds($ids);
}
function noticesWithFriends($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null)
@@ -444,21 +436,17 @@ class User extends Memcached_DataObject
'SELECT notice.* ' .
'FROM notice JOIN subscription ON notice.profile_id = subscription.subscribed ' .
'WHERE subscription.subscriber = %d ';
- $order = null;
+ return Notice::getStream(sprintf($qry, $this->id),
+ 'user:notices_with_friends:' . $this->id,
+ $offset, $limit, $since_id, $before_id,
+ $order, $since);
} else if ($enabled === true ||
($enabled == 'transitional' && $this->inboxed == 1)) {
- $qry =
- 'SELECT notice.* ' .
- 'FROM notice JOIN notice_inbox ON notice.id = notice_inbox.notice_id ' .
- 'WHERE notice_inbox.user_id = %d ';
- // NOTE: we override ORDER
- $order = null;
- }
- return Notice::getStream(sprintf($qry, $this->id),
- 'user:notices_with_friends:' . $this->id,
- $offset, $limit, $since_id, $before_id,
- $order, $since);
+ $ids = Notice_inbox::stream($this->id, $offset, $limit, $since_id, $before_id, $since);
+
+ return Notice::getStreamByIds($ids);
+ }
}
function blowFavesCache()
@@ -467,8 +455,8 @@ class User extends Memcached_DataObject
if ($cache) {
// Faves don't happen chronologically, so we need to blow
// ;last cache, too
- $cache->delete(common_cache_key('user:faves:'.$this->id));
- $cache->delete(common_cache_key('user:faves:'.$this->id).';last');
+ $cache->delete(common_cache_key('fave:ids_by_user:'.$this->id));
+ $cache->delete(common_cache_key('fave:ids_by_user:'.$this->id.';last'));
}
}
diff --git a/classes/User_group.php b/classes/User_group.php
index d152f9d56..7cc31e702 100755
--- a/classes/User_group.php
+++ b/classes/User_group.php
@@ -50,13 +50,50 @@ class User_group extends Memcached_DataObject
function getNotices($offset, $limit)
{
- $qry =
- 'SELECT notice.* ' .
- 'FROM notice JOIN group_inbox ON notice.id = group_inbox.notice_id ' .
- 'WHERE group_inbox.group_id = %d ';
- return Notice::getStream(sprintf($qry, $this->id),
- 'group:notices:'.$this->id,
- $offset, $limit);
+ $ids = Notice::stream(array($this, '_streamDirect'),
+ array(),
+ 'user_group:notice_ids:' . $this->id,
+ $offset, $limit);
+
+ return Notice::getStreamByIds($ids);
+ }
+
+ function _streamDirect($offset, $limit, $since_id, $before_id, $since)
+ {
+ $inbox = new Group_inbox();
+
+ $inbox->group_id = $this->id;
+
+ $inbox->selectAdd();
+ $inbox->selectAdd('notice_id');
+
+ if ($since_id != 0) {
+ $inbox->whereAdd('notice_id > ' . $since_id);
+ }
+
+ if ($before_id != 0) {
+ $inbox->whereAdd('notice_id < ' . $before_id);
+ }
+
+ if (!is_null($since)) {
+ $inbox->whereAdd('created > \'' . date('Y-m-d H:i:s', $since) . '\'');
+ }
+
+ $inbox->orderBy('notice_id DESC');
+
+ if (!is_null($offset)) {
+ $inbox->limit($offset, $limit);
+ }
+
+ $ids = array();
+
+ if ($inbox->find()) {
+ while ($inbox->fetch()) {
+ $ids[] = $inbox->notice_id;
+ }
+ }
+
+ return $ids;
}
function allowedNickname($nickname)
@@ -91,7 +128,7 @@ class User_group extends Memcached_DataObject
function setOriginal($filename)
{
$imagefile = new ImageFile($this->id, Avatar::path($filename));
-
+
$orig = clone($this);
$this->original_logo = Avatar::url($filename);
$this->homepage_logo = Avatar::url($imagefile->resize(AVATAR_PROFILE_SIZE));
diff --git a/classes/laconica.ini b/classes/laconica.ini
index 529454d99..c05419588 100755
--- a/classes/laconica.ini
+++ b/classes/laconica.ini
@@ -55,6 +55,8 @@ credentials = 2
noticesync = 145
friendsync = 145
profilesync = 145
+last_noticesync = 14
+last_friendsync = 14
created = 142
modified = 384