X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=classes%2FNotice.php;h=3f6c5cebbeacf1451c45aaa291e2ef2917326c33;hb=78f8b91a13ee07ed3344fd6411a0829a16bef4b1;hp=44a6aeb986914b4ab6c6c8ccc8987d2a67443329;hpb=5385692ff37e619de29e3c811a01c1a62414dd6f;p=quix0rs-gnu-social.git diff --git a/classes/Notice.php b/classes/Notice.php index 44a6aeb986..3f6c5cebbe 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -67,6 +67,8 @@ class Notice extends Memcached_DataObject $this->blowSubsCache(true); $this->query('BEGIN'); + //Null any notices that are replies to this notice + $this->query(sprintf("UPDATE notice set reply_to = null WHERE reply_to = %d", $this->id)); $related = array('Reply', 'Fave', 'Notice_tag', @@ -193,9 +195,14 @@ class Notice extends Memcached_DataObject $notice->saveReplies(); $notice->saveTags(); - $notice->saveGroups(); - $notice->addToInboxes(); + if (common_config('queue', 'enabled')) { + $notice->addToAuthorInbox(); + } else { + $notice->addToInboxes(); + $notice->saveGroups(); + } + $notice->query('COMMIT'); Event::handle('EndNoticeSave', array($notice)); @@ -205,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; @@ -269,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(); @@ -277,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')); } } } @@ -306,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(); @@ -330,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(); @@ -344,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')); } } } @@ -361,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')); } } } @@ -393,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')); } } } @@ -407,22 +426,22 @@ class Notice extends Memcached_DataObject # XXX: too many args; we need to move to named params or even a separate # class for notice streams - static function getStream($qry, $cachekey, $offset=0, $limit=20, $since_id=0, $before_id=0, $order=null, $since=null) { + static function getStream($qry, $cachekey, $offset=0, $limit=20, $since_id=0, $max_id=0, $order=null, $since=null) { if (common_config('memcached', 'enabled')) { - # Skip the cache if this is a since, since_id or before_id qry - if ($since_id > 0 || $before_id > 0 || $since) { - return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order, $since); + # Skip the cache if this is a since, since_id or max_id qry + if ($since_id > 0 || $max_id > 0 || $since) { + return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $max_id, $order, $since); } else { return Notice::getCachedStream($qry, $cachekey, $offset, $limit, $order); } } - return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order, $since); + return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $max_id, $order, $since); } - static function getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order, $since) { + static function getStreamDirect($qry, $offset, $limit, $since_id, $max_id, $order, $since) { $needAnd = false; $needWhere = true; @@ -444,7 +463,7 @@ class Notice extends Memcached_DataObject $qry .= ' notice.id > ' . $since_id; } - if ($before_id > 0) { + if ($max_id > 0) { if ($needWhere) { $qry .= ' WHERE '; @@ -453,7 +472,7 @@ class Notice extends Memcached_DataObject $qry .= ' AND '; } - $qry .= ' notice.id < ' . $before_id; + $qry .= ' notice.id <= ' . $max_id; } if ($since) { @@ -591,27 +610,80 @@ class Notice extends Memcached_DataObject return $wrapper; } - function publicStream($offset=0, $limit=20, $since_id=0, $before_id=0, $since=null) + 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, $max_id=0, $since=null) + { + $ids = Notice::stream(array('Notice', '_publicStreamDirect'), + array(), + 'public', + $offset, $limit, $since_id, $max_id, $since); + + return Notice::getStreamByIds($ids); + } + + function _publicStreamDirect($offset=0, $limit=20, $since_id=0, $max_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 ($max_id != 0) { + $notice->whereAdd('id <= ' . $max_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() @@ -637,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'); @@ -689,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 @@ -893,4 +997,59 @@ class Notice extends Memcached_DataObject array('notice' => $this->id)); } } + + function stream($fn, $args, $cachekey, $offset=0, $limit=20, $since_id=0, $max_id=0, $since=null) + { + $cache = common_memcache(); + + if (empty($cache) || + $since_id != 0 || $max_id != 0 || !is_null($since) || + ($offset + $limit) > NOTICE_CACHE_WINDOW) { + return call_user_func_array($fn, array_merge($args, array($offset, $limit, $since_id, + $max_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; + } }