From: Michael Date: Wed, 18 Oct 2023 08:11:36 +0000 (+0000) Subject: Improve the performance of API timeline calls X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=1c67be8db0f051f8c983080bfabe83b432531ed7;p=friendica.git Improve the performance of API timeline calls --- diff --git a/database.sql b/database.sql index 05fbe131f7..a6e29826be 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2023.09-rc (Giant Rhubarb) --- DB_UPDATE_VERSION 1537 +-- DB_UPDATE_VERSION 1538 -- ------------------------------------------ @@ -1991,6 +1991,51 @@ CREATE VIEW `circle-member-view` AS SELECT INNER JOIN `contact` ON `group_member`.`contact-id` = `contact`.`id` INNER JOIN `group` ON `group_member`.`gid` = `group`.`id`; +-- +-- VIEW post-timeline-view +-- +DROP VIEW IF EXISTS `post-timeline-view`; +CREATE VIEW `post-timeline-view` AS SELECT + `post-user`.`uid` AS `uid`, + `post-user`.`uri-id` AS `uri-id`, + `post-user`.`gravity` AS `gravity`, + `post-user`.`created` AS `created`, + `post-user`.`edited` AS `edited`, + `post-thread-user`.`commented` AS `commented`, + `post-user`.`received` AS `received`, + `post-thread-user`.`changed` AS `changed`, + `post-user`.`private` AS `private`, + `post-user`.`visible` AS `visible`, + `post-user`.`deleted` AS `deleted`, + `post-user`.`origin` AS `origin`, + `post-user`.`global` AS `global`, + `post-user`.`network` AS `network`, + `post-user`.`protocol` AS `protocol`, + `post-user`.`vid` AS `vid`, + `post-user`.`contact-id` AS `contact-id`, + `contact`.`blocked` AS `contact-blocked`, + `contact`.`readonly` AS `contact-readonly`, + `contact`.`pending` AS `contact-pending`, + `contact`.`rel` AS `contact-rel`, + `contact`.`uid` AS `contact-uid`, + `contact`.`self` AS `self`, + `post-user`.`author-id` AS `author-id`, + `author`.`blocked` AS `author-blocked`, + `author`.`hidden` AS `author-hidden`, + `author`.`gsid` AS `author-gsid`, + `post-user`.`owner-id` AS `owner-id`, + `owner`.`blocked` AS `owner-blocked`, + `owner`.`gsid` AS `owner-gsid`, + `post-user`.`causer-id` AS `causer-id`, + `causer`.`blocked` AS `causer-blocked`, + `causer`.`gsid` AS `causer-gsid` + FROM `post-user` + LEFT JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` + STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id` + STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `post-user`.`author-id` + STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-user`.`owner-id` + LEFT JOIN `contact` AS `causer` ON `causer`.`id` = `post-user`.`causer-id`; + -- -- VIEW post-user-view -- diff --git a/src/Model/Post.php b/src/Model/Post.php index fe48450221..323b307fcd 100644 --- a/src/Model/Post.php +++ b/src/Model/Post.php @@ -497,6 +497,23 @@ class Post return self::selectViewForUser('post-view', $uid, $selected, $condition, $params); } + /** + * Select rows from the post-timeline-view view for a given user + * This function is used for API calls. + * + * @param integer $uid User ID + * @param array $selected Array of selected fields, empty for all + * @param array $condition Array of fields for condition + * @param array $params Array of several parameters + * + * @return boolean|object + * @throws \Exception + */ + public static function selectTimelineForUser(int $uid, array $selected = [], array $condition = [], array $params = []) + { + return self::selectViewForUser('post-timeline-view', $uid, $selected, $condition, $params); + } + /** * Select rows from the post-thread-user-view view for a given user * diff --git a/src/Module/Api/Mastodon/Accounts/Statuses.php b/src/Module/Api/Mastodon/Accounts/Statuses.php index b4e09b613e..9093b5eab8 100644 --- a/src/Module/Api/Mastodon/Accounts/Statuses.php +++ b/src/Module/Api/Mastodon/Accounts/Statuses.php @@ -74,8 +74,10 @@ class Statuses extends BaseApi } elseif ($request['only_media']) { $condition = ['author-id' => $id, 'private' => [Item::PUBLIC, Item::UNLISTED], 'type' => [Post\Media::AUDIO, Post\Media::IMAGE, Post\Media::VIDEO]]; } elseif (!$uid) { - $condition = ['author-id' => $id, 'private' => [Item::PUBLIC, Item::UNLISTED], - 'uid' => 0, 'network' => Protocol::FEDERATED]; + $condition = [ + 'author-id' => $id, 'private' => [Item::PUBLIC, Item::UNLISTED], + 'uid' => 0, 'network' => Protocol::FEDERATED + ]; } else { $condition = ["`author-id` = ? AND (`uid` = 0 OR (`uid` = ? AND NOT `global`))", $id, $uid]; } @@ -85,11 +87,15 @@ class Statuses extends BaseApi if (!$request['pinned'] && !$request['only_media']) { if ($request['exclude_replies']) { - $condition = DBA::mergeConditions($condition, ["(`gravity` = ? OR (`gravity` = ? AND `vid` = ? AND `protocol` != ?))", - Item::GRAVITY_PARENT, Item::GRAVITY_ACTIVITY, Verb::getID(Activity::ANNOUNCE), Conversation::PARCEL_DIASPORA]); + $condition = DBA::mergeConditions($condition, [ + "(`gravity` = ? OR (`gravity` = ? AND `vid` = ? AND `protocol` != ?))", + Item::GRAVITY_PARENT, Item::GRAVITY_ACTIVITY, Verb::getID(Activity::ANNOUNCE), Conversation::PARCEL_DIASPORA + ]); } else { - $condition = DBA::mergeConditions($condition, ["(`gravity` IN (?, ?) OR (`gravity` = ? AND `vid` = ? AND `protocol` != ?))", - Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT, Item::GRAVITY_ACTIVITY, Verb::getID(Activity::ANNOUNCE), Conversation::PARCEL_DIASPORA]); + $condition = DBA::mergeConditions($condition, [ + "(`gravity` IN (?, ?) OR (`gravity` = ? AND `vid` = ? AND `protocol` != ?))", + Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT, Item::GRAVITY_ACTIVITY, Verb::getID(Activity::ANNOUNCE), Conversation::PARCEL_DIASPORA + ]); } } elseif ($request['exclude_replies']) { $condition = DBA::mergeConditions($condition, ['gravity' => Item::GRAVITY_PARENT]); @@ -100,7 +106,7 @@ class Statuses extends BaseApi } elseif ($request['only_media']) { $items = DBA::select('media-view', ['uri-id'], $condition, $params); } else { - $items = Post::selectForUser($uid, ['uri-id'], $condition, $params); + $items = Post::selectTimelineForUser($uid, ['uri-id'], $condition, $params); } $display_quotes = self::appSupportsQuotes(); diff --git a/src/Module/Api/Mastodon/Timelines/Home.php b/src/Module/Api/Mastodon/Timelines/Home.php index d92a87636f..80d4826291 100644 --- a/src/Module/Api/Mastodon/Timelines/Home.php +++ b/src/Module/Api/Mastodon/Timelines/Home.php @@ -22,7 +22,6 @@ namespace Friendica\Module\Api\Mastodon\Timelines; use Friendica\Core\Logger; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Item; @@ -67,8 +66,10 @@ class Home extends BaseApi } if ($request['only_media']) { - $condition = DBA::mergeConditions($condition, ["`uri-id` IN (SELECT `uri-id` FROM `post-media` WHERE `type` IN (?, ?, ?))", - Post\Media::AUDIO, Post\Media::IMAGE, Post\Media::VIDEO]); + $condition = DBA::mergeConditions($condition, [ + "`uri-id` IN (SELECT `uri-id` FROM `post-media` WHERE `type` IN (?, ?, ?))", + Post\Media::AUDIO, Post\Media::IMAGE, Post\Media::VIDEO + ]); } if ($request['remote']) { @@ -79,7 +80,7 @@ class Home extends BaseApi $condition = DBA::mergeConditions($condition, ['gravity' => Item::GRAVITY_PARENT]); } - $items = Post::selectForUser($uid, ['uri-id'], $condition, $params); + $items = Post::selectTimelineForUser($uid, ['uri-id'], $condition, $params); $display_quotes = self::appSupportsQuotes(); diff --git a/src/Module/Api/Mastodon/Timelines/ListTimeline.php b/src/Module/Api/Mastodon/Timelines/ListTimeline.php index 4331fc321c..147693f891 100644 --- a/src/Module/Api/Mastodon/Timelines/ListTimeline.php +++ b/src/Module/Api/Mastodon/Timelines/ListTimeline.php @@ -61,15 +61,19 @@ class ListTimeline extends BaseApi 'friendica_order' => TimelineOrderByTypes::ID, // Sort order options (defaults to ID) ], $request); - $condition = ["`uid` = ? AND `gravity` IN (?, ?) AND `contact-id` IN (SELECT `contact-id` FROM `group_member` WHERE `gid` = ?)", - $uid, Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT, $this->parameters['id']]; + $condition = [ + "`uid` = ? AND `gravity` IN (?, ?) AND `contact-id` IN (SELECT `contact-id` FROM `group_member` WHERE `gid` = ?)", + $uid, Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT, $this->parameters['id'] + ]; $condition = $this->addPagingConditions($request, $condition); $params = $this->buildOrderAndLimitParams($request); if ($request['only_media']) { - $condition = DBA::mergeConditions($condition, ["`uri-id` IN (SELECT `uri-id` FROM `post-media` WHERE `type` IN (?, ?, ?))", - Post\Media::AUDIO, Post\Media::IMAGE, Post\Media::VIDEO]); + $condition = DBA::mergeConditions($condition, [ + "`uri-id` IN (SELECT `uri-id` FROM `post-media` WHERE `type` IN (?, ?, ?))", + Post\Media::AUDIO, Post\Media::IMAGE, Post\Media::VIDEO + ]); } if ($request['exclude_replies']) { @@ -84,7 +88,7 @@ class ListTimeline extends BaseApi $condition = DBA::mergeConditions($condition, ["NOT `uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `origin` AND `post-user`.`uri-id` = `post-user-view`.`uri-id`)"]); } - $items = Post::selectForUser($uid, ['uri-id'], $condition, $params); + $items = Post::selectTimelineForUser($uid, ['uri-id'], $condition, $params); $display_quotes = self::appSupportsQuotes(); diff --git a/src/Module/Api/Mastodon/Timelines/PublicTimeline.php b/src/Module/Api/Mastodon/Timelines/PublicTimeline.php index 057e2ec8d0..2692ca84b4 100644 --- a/src/Module/Api/Mastodon/Timelines/PublicTimeline.php +++ b/src/Module/Api/Mastodon/Timelines/PublicTimeline.php @@ -23,7 +23,6 @@ namespace Friendica\Module\Api\Mastodon\Timelines; use Friendica\Core\Logger; use Friendica\Core\Protocol; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Item; @@ -57,30 +56,36 @@ class PublicTimeline extends BaseApi 'friendica_order' => TimelineOrderByTypes::ID, // Sort order options (defaults to ID) ], $request); - $condition = ['gravity' => [Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT], 'private' => Item::PUBLIC, - 'network' => Protocol::FEDERATED, 'author-blocked' => false, 'author-hidden' => false]; + $condition = [ + 'gravity' => [Item::GRAVITY_PARENT, Item::GRAVITY_COMMENT], 'private' => Item::PUBLIC, + 'network' => Protocol::FEDERATED, 'author-blocked' => false, 'author-hidden' => false + ]; $condition = $this->addPagingConditions($request, $condition); $params = $this->buildOrderAndLimitParams($request); if ($request['local']) { - $condition = DBA::mergeConditions($condition, ["`uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `origin`)"]); + $condition = DBA::mergeConditions($condition, ['origin' => true]); + } else { + $condition = DBA::mergeConditions($condition, ['uid' => 0]); } if ($request['remote']) { - $condition = DBA::mergeConditions($condition, ["NOT `uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `origin` AND `post-user`.`uri-id` = `post-view`.`uri-id`)"]); + $condition = DBA::mergeConditions($condition, ["NOT `uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `origin` AND `post-user`.`uri-id` = `post-timeline-view`.`uri-id`)"]); } if ($request['only_media']) { - $condition = DBA::mergeConditions($condition, ["`uri-id` IN (SELECT `uri-id` FROM `post-media` WHERE `type` IN (?, ?, ?))", - Post\Media::AUDIO, Post\Media::IMAGE, Post\Media::VIDEO]); + $condition = DBA::mergeConditions($condition, [ + "`uri-id` IN (SELECT `uri-id` FROM `post-media` WHERE `type` IN (?, ?, ?))", + Post\Media::AUDIO, Post\Media::IMAGE, Post\Media::VIDEO + ]); } if ($request['exclude_replies']) { $condition = DBA::mergeConditions($condition, ['gravity' => Item::GRAVITY_PARENT]); } - $items = Post::selectPostsForUser($uid, ['uri-id'], $condition, $params); + $items = Post::selectTimelineForUser($uid, ['uri-id'], $condition, $params); $display_quotes = self::appSupportsQuotes(); diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index b7a37708cd..e97d1ea1cd 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -56,7 +56,7 @@ use Friendica\Database\DBA; // This file is required several times during the test in DbaDefinition which justifies this condition if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1537); + define('DB_UPDATE_VERSION', 1538); } return [ diff --git a/static/dbview.config.php b/static/dbview.config.php index 057c8fccc5..b4d10de83c 100644 --- a/static/dbview.config.php +++ b/static/dbview.config.php @@ -87,6 +87,49 @@ INNER JOIN `contact` ON `group_member`.`contact-id` = `contact`.`id` INNER JOIN `group` ON `group_member`.`gid` = `group`.`id`" ], + "post-timeline-view" => [ + "fields" => [ + "uid" => ["post-user", "uid"], + "uri-id" => ["post-user", "uri-id"], + "gravity" => ["post-user", "gravity"], + "created" => ["post-user", "created"], + "edited" => ["post-user", "edited"], + "commented" => ["post-thread-user", "commented"], + "received" => ["post-user", "received"], + "changed" => ["post-thread-user", "changed"], + "private" => ["post-user", "private"], + "visible" => ["post-user", "visible"], + "deleted" => ["post-user", "deleted"], + "origin" => ["post-user", "origin"], + "global" => ["post-user", "global"], + "network" => ["post-user", "network"], + "protocol" => ["post-user", "protocol"], + "vid" => ["post-user", "vid"], + "contact-id" => ["post-user", "contact-id"], + "contact-blocked" => ["contact", "blocked"], + "contact-readonly" => ["contact", "readonly"], + "contact-pending" => ["contact", "pending"], + "contact-rel" => ["contact", "rel"], + "contact-uid" => ["contact", "uid"], + "self" => ["contact", "self"], + "author-id" => ["post-user", "author-id"], + "author-blocked" => ["author", "blocked"], + "author-hidden" => ["author", "hidden"], + "author-gsid" => ["author", "gsid"], + "owner-id" => ["post-user", "owner-id"], + "owner-blocked" => ["owner", "blocked"], + "owner-gsid" => ["owner", "gsid"], + "causer-id" => ["post-user", "causer-id"], + "causer-blocked" => ["causer", "blocked"], + "causer-gsid" => ["causer", "gsid"], + ], + "query" => "FROM `post-user` + LEFT JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-user`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-user`.`uid` + STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id` + STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `post-user`.`author-id` + STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-user`.`owner-id` + LEFT JOIN `contact` AS `causer` ON `causer`.`id` = `post-user`.`causer-id`" + ], "post-user-view" => [ "fields" => [ "id" => ["post-user", "id"],