1
0
Эх сурвалжийг харах

Improve reblog api performance

Daniel Supernault 3 жил өмнө
parent
commit
3ef6c9fe81

+ 20 - 20
app/Http/Controllers/Api/ApiV1Controller.php

@@ -1879,7 +1879,7 @@ class ApiV1Controller extends Controller
 
 
 		if($status->profile_id !== $user->profile_id) {
 		if($status->profile_id !== $user->profile_id) {
 			if($status->scope == 'private') {
 			if($status->scope == 'private') {
-				abort_if(!$status->profile->followedBy($user->profile), 403);
+				abort_if(!FollowerService::follows($user->profile_id, $status->profile_id), 403);
 			} else {
 			} else {
 				abort_if(!in_array($status->scope, ['public','unlisted']), 403);
 				abort_if(!in_array($status->scope, ['public','unlisted']), 403);
 			}
 			}
@@ -1922,22 +1922,7 @@ class ApiV1Controller extends Controller
 	public function statusCard(Request $request, $id)
 	public function statusCard(Request $request, $id)
 	{
 	{
 		abort_if(!$request->user(), 403);
 		abort_if(!$request->user(), 403);
-
-		$user = $request->user();
-
-		$status = Status::findOrFail($id);
-
-		if($status->profile_id !== $user->profile_id) {
-			if($status->scope == 'private') {
-				abort_if(!$status->profile->followedBy($user->profile), 403);
-			} else {
-				abort_if(!in_array($status->scope, ['public','unlisted']), 403);
-			}
-		}
-
-		// Return empty response since we don't handle support cards
 		$res = [];
 		$res = [];
-
 		return response()->json($res);
 		return response()->json($res);
 	}
 	}
 
 
@@ -1963,15 +1948,30 @@ class ApiV1Controller extends Controller
 
 
 		if($status->profile_id !== $user->profile_id) {
 		if($status->profile_id !== $user->profile_id) {
 			if($status->scope == 'private') {
 			if($status->scope == 'private') {
-				abort_if(!$status->profile->followedBy($user->profile), 403);
+				abort_if(!FollowerService::follows($user->profile_id, $status->profile_id), 403);
 			} else {
 			} else {
 				abort_if(!in_array($status->scope, ['public','unlisted']), 403);
 				abort_if(!in_array($status->scope, ['public','unlisted']), 403);
 			}
 			}
 		}
 		}
 
 
-		$shared = $status->sharedBy()->latest()->simplePaginate($limit);
-		$resource = new Fractal\Resource\Collection($shared, new AccountTransformer());
-		$res = $this->fractal->createData($resource)->toArray();
+		$page = $request->input('page', 1);
+		$start = $page == 1 ? 0 : (($page * $limit) - $limit);
+		$end = $start + $limit - 1;
+
+		$ids = ReblogService::getPostReblogs($id, $start, $end);
+		if(empty($ids)) {
+			return [];
+		}
+
+		$res = collect($ids)
+			->map(function($id) {
+				$status = StatusService::get($id);
+				return AccountService::get($status['account']['id']);
+			})
+			->filter(function($account) {
+				return $account && isset($account['id']);
+			})
+			->values();
 
 
 		$url = $request->url();
 		$url = $request->url();
 		$page = $request->input('page', 1);
 		$page = $request->input('page', 1);

+ 3 - 0
app/Jobs/SharePipeline/SharePipeline.php

@@ -15,6 +15,7 @@ use League\Fractal\Serializer\ArraySerializer;
 use App\Transformer\ActivityPub\Verb\Announce;
 use App\Transformer\ActivityPub\Verb\Announce;
 use GuzzleHttp\{Pool, Client, Promise};
 use GuzzleHttp\{Pool, Client, Promise};
 use App\Util\ActivityPub\HttpSignature;
 use App\Util\ActivityPub\HttpSignature;
+use App\Services\ReblogService;
 use App\Services\StatusService;
 use App\Services\StatusService;
 
 
 class SharePipeline implements ShouldQueue
 class SharePipeline implements ShouldQueue
@@ -75,6 +76,8 @@ class SharePipeline implements ShouldQueue
 
 
 		$this->remoteAnnounceDeliver();
 		$this->remoteAnnounceDeliver();
 
 
+		ReblogService::addPostReblog($parent->id, $status->id);
+
 		$parent->reblogs_count = $parent->shares()->count();
 		$parent->reblogs_count = $parent->shares()->count();
 		$parent->save();
 		$parent->save();
 		StatusService::del($parent->id);
 		StatusService::del($parent->id);

+ 3 - 0
app/Jobs/SharePipeline/UndoSharePipeline.php

@@ -15,6 +15,7 @@ use League\Fractal\Serializer\ArraySerializer;
 use App\Transformer\ActivityPub\Verb\UndoAnnounce;
 use App\Transformer\ActivityPub\Verb\UndoAnnounce;
 use GuzzleHttp\{Pool, Client, Promise};
 use GuzzleHttp\{Pool, Client, Promise};
 use App\Util\ActivityPub\HttpSignature;
 use App\Util\ActivityPub\HttpSignature;
+use App\Services\ReblogService;
 use App\Services\StatusService;
 use App\Services\StatusService;
 
 
 class UndoSharePipeline implements ShouldQueue
 class UndoSharePipeline implements ShouldQueue
@@ -35,6 +36,8 @@ class UndoSharePipeline implements ShouldQueue
 		$parent = $status->parent();
 		$parent = $status->parent();
 		$target = $status->parent()->profile;
 		$target = $status->parent()->profile;
 
 
+		ReblogService::removePostReblog($parent->id, $status->id);
+
 		if ($status->uri !== null) {
 		if ($status->uri !== null) {
 			return;
 			return;
 		}
 		}

+ 31 - 0
app/Services/ReblogService.php

@@ -2,11 +2,15 @@
 
 
 namespace App\Services;
 namespace App\Services;
 
 
+use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\Redis;
 use Illuminate\Support\Facades\Redis;
+use App\Status;
 
 
 class ReblogService
 class ReblogService
 {
 {
 	const CACHE_KEY = 'pf:services:reblogs:';
 	const CACHE_KEY = 'pf:services:reblogs:';
+	const REBLOGS_KEY = 'pf:services:reblogs:post:';
+	const COLDBOOT_KEY = 'pf:services:reblogs:post_:';
 
 
 	public static function get($profileId, $statusId)
 	public static function get($profileId, $statusId)
 	{
 	{
@@ -26,4 +30,31 @@ class ReblogService
 	{
 	{
 		return Redis::zrem(self::CACHE_KEY . $profileId, $statusId);
 		return Redis::zrem(self::CACHE_KEY . $profileId, $statusId);
 	}
 	}
+
+	public static function getPostReblogs($id, $start = 0, $stop = 10)
+	{
+		if(!Redis::zcard(self::REBLOGS_KEY . $id)) {
+			return Cache::remember(self::COLDBOOT_KEY . $id, 86400, function() use($id) {
+				return Status::whereReblogOfId($id)
+					->pluck('id')
+					->each(function($reblog) use($id) {
+						self::addPostReblog($id, $reblog);
+					})
+					->map(function($reblog) {
+						return (string) $reblog;
+					});
+			});
+		}
+		return Redis::zrange(self::REBLOGS_KEY . $id, $start, $stop);
+	}
+
+	public static function addPostReblog($parentId, $reblogId)
+	{
+		return Redis::zadd(self::REBLOGS_KEY . $parentId, $reblogId);
+	}
+
+	public static function removePostReblog($parentId, $reblogId)
+	{
+		return Redis::zrem(self::REBLOGS_KEY . $parentId, $reblogId);
+	}
 }
 }