diff --git a/lib/notices/cachingnoticestream.php b/lib/notices/cachingnoticestream.php
index e68bb3a1f2..669535c58a 100644
--- a/lib/notices/cachingnoticestream.php
+++ b/lib/notices/cachingnoticestream.php
@@ -1,66 +1,96 @@
.
+
/**
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2011, StatusNet, Inc.
- *
* A stream of notices
*
- * PHP version 5
- *
- * 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
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- *
* @category Stream
- * @package StatusNet
+ * @package GNUsocial
* @author Evan Prodromou
* @copyright 2011 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link http://status.net/
+ * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
-if (!defined('STATUSNET')) {
- // This check helps protect against security problems;
- // your code file can't be executed directly from the web.
- exit(1);
-}
+defined('GNUSOCIAL') || die();
/**
* Class for notice streams
*
* @category Stream
- * @package StatusNet
+ * @package GNUsocial
* @author Evan Prodromou
* @copyright 2011 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link http://status.net/
+ * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class CachingNoticeStream extends NoticeStream
{
const CACHE_WINDOW = 200;
- public $stream = null;
- public $cachekey = null;
- public $useLast = true;
+ public $stream = null;
+ public $cachekey = null;
+ public $useLast = true;
+ public $alwaysCheck = true;
- function __construct($stream, $cachekey, $useLast = true)
- {
- $this->stream = $stream;
- $this->cachekey = $cachekey;
- $this->useLast = $useLast;
+ public function __construct(
+ NoticeStream $stream,
+ string $cachekey,
+ bool $useLast = true,
+ bool $alwaysCheck = false
+ ) {
+ $this->stream = $stream;
+ $this->cachekey = $cachekey;
+ $this->useLast = $useLast;
+ $this->alwaysCheck = $alwaysCheck;
}
- function getNoticeIds($offset, $limit, $sinceId, $maxId)
+ private function getCacheNoticeIds(
+ Cache $cache,
+ string $idkey,
+ bool $check = false
+ ): ?array {
+ $id_str = $cache->get($idkey);
+
+ if ($id_str === false) {
+ return null;
+ }
+
+ $ids = explode(',', $id_str);
+
+ if ($check) {
+ $latest_id = $ids[0];
+ $new_ids = $this->stream->getNoticeIds(
+ 0,
+ self::CACHE_WINDOW,
+ $latest_id,
+ null
+ );
+
+ $ids = array_merge($new_ids, $ids);
+ $ids = array_slice($ids, 0, self::CACHE_WINDOW);
+
+ $new_id_str = implode(',', $ids);
+ if ($id_str !== $new_id_str) {
+ $cache->set($idkey, $new_id_str);
+ }
+ }
+ return $ids;
+ }
+
+ public function getNoticeIds($offset, $limit, $sinceId, $maxId)
{
$cache = Cache::instance();
@@ -78,13 +108,11 @@ class CachingNoticeStream extends NoticeStream
$idkey = Cache::key($this->cachekey);
- $idstr = $cache->get($idkey);
+ $ids = $this->getCacheNoticeIds($cache, $idkey, $this->alwaysCheck);
- if ($idstr !== false) {
+ if (!is_null($ids)) {
// Cache hit! Woohoo!
- $window = explode(',', $idstr);
- $ids = array_slice($window, $offset, $limit);
- return $ids;
+ return array_slice($ids, $offset, $limit);
}
if ($this->useLast) {
@@ -94,43 +122,31 @@ class CachingNoticeStream extends NoticeStream
// a few at the "tip", which can bound our queries and save lots
// of time.
- $laststr = $cache->get($idkey.';last');
+ $ids = $this->getCacheNoticeIds($cache, $idkey . ';last', true);
- if ($laststr !== false) {
- $window = explode(',', $laststr);
- $last_id = $window[0];
- $new_ids = $this->stream->getNoticeIds(0, self::CACHE_WINDOW, $last_id, 0);
+ if (!is_null($ids)) {
+ // Set the actual cache value as well
+ $id_str = implode(',', $ids);
+ $cache->set($idkey, $id_str);
- $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;
+ return array_slice($ids, $offset, $limit);
}
}
// No cache hits :( Generate directly and stick the results
// into the cache. Note we generate the full cache window.
- $window = $this->stream->getNoticeIds(0, self::CACHE_WINDOW, 0, 0);
+ $window = $this->stream->getNoticeIds(0, self::CACHE_WINDOW, null, null);
$windowstr = implode(',', $window);
- $result = $cache->set($idkey, $windowstr);
+ $cache->set($idkey, $windowstr);
if ($this->useLast) {
- $result = $cache->set($idkey . ';last', $windowstr);
+ $cache->set($idkey . ';last', $windowstr);
}
// Return just the slice that was requested
-
- $ids = array_slice($window, $offset, $limit);
-
- return $ids;
+ return array_slice($window, $offset, $limit);
}
}
diff --git a/lib/notices/inboxnoticestream.php b/lib/notices/inboxnoticestream.php
index 8eb03aeb4a..bc0cb62eec 100644
--- a/lib/notices/inboxnoticestream.php
+++ b/lib/notices/inboxnoticestream.php
@@ -46,7 +46,15 @@ class InboxNoticeStream extends ScopingNoticeStream
*/
public function __construct(Profile $target, Profile $scoped = null)
{
- parent::__construct(new CachingNoticeStream(new RawInboxNoticeStream($target), 'profileall:'.$target->getID()), $scoped);
+ parent::__construct(
+ new CachingNoticeStream(
+ new RawInboxNoticeStream($target),
+ 'profileall:' . $target->getID(),
+ false,
+ true
+ ),
+ $scoped
+ );
}
}