Merge pull request #7447 from pixelfed/staging

Refactor DirectMessageController@composeMutuals endpoint
dev
dansup 9 hours ago committed by GitHub
commit e1df7d657c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -385,17 +385,6 @@ class DirectMessageController extends Controller
$res = FollowerService::getMutualsWithProfiles($user->profile_id, 10, $cursor); $res = FollowerService::getMutualsWithProfiles($user->profile_id, 10, $cursor);
if ($cursor && $res && isset($res['total_count']) && is_int($res['total_count']) && $res['total_count'] > 100) {
$empty = [
'data' => [],
'has_more' => false,
'next_cursor' => false,
'total_count' => $res['total_count'],
];
return response()->json($empty);
}
return response()->json($res); return response()->json($res);
} }

@ -27,6 +27,8 @@ class FollowerService
const FOLLOWERS_MUTUALS_KEY = 'pf:services:follow:mutuals:v2:'; const FOLLOWERS_MUTUALS_KEY = 'pf:services:follow:mutuals:v2:';
const MUTUALS_DM_MAX_PAGES = 5;
public static function add($actor, $target, $refresh = true) public static function add($actor, $target, $refresh = true)
{ {
$ts = (int) microtime(true); $ts = (int) microtime(true);
@ -301,29 +303,32 @@ class FollowerService
} }
/** /**
* Get mutual followers for DM suggestions using Redis set intersection * Get mutual followers for DM suggestions, newest mutuals first.
* This is extremely fast as it operates entirely in Redis memory * Pagination is capped internally at MUTUALS_DM_MAX_PAGES pages.
* *
* @param int $profileId * @param int $profileId
* @param int $limit * @param int $limit
* @param int|null $cursor * @param int|null $cursor Profile id of the last item seen
*/ */
public static function getMutualsForDM($profileId, $limit = 20, $cursor = null): array public static function getMutualsForDM($profileId, $limit = 20, $cursor = null): array
{ {
$empty = [
'data' => [],
'has_more' => false,
'next_cursor' => null,
'total_count' => 0,
];
$acct = AccountService::get($profileId, true); $acct = AccountService::get($profileId, true);
if (! $acct || ! isset($acct['id'])) { if (! $acct || ! isset($acct['id'])) {
return [ return $empty;
'data' => [],
'has_more' => false,
'next_cursor' => null,
'total_count' => 0,
];
} }
self::cacheSyncCheck($profileId, 'followers'); self::cacheSyncCheck($profileId, 'followers');
self::cacheSyncCheck($profileId, 'following'); self::cacheSyncCheck($profileId, 'following');
$mutualsKey = self::warmMutuals($profileId); $mutualsKey = self::warmMutuals($profileId);
$totalCount = Redis::zcard($mutualsKey);
$start = 0; $start = 0;
@ -334,20 +339,28 @@ class FollowerService
} }
} }
$mutuals = Redis::zrevrange($mutualsKey, $start, $start + $limit); $maxItems = self::MUTUALS_DM_MAX_PAGES * $limit;
if ($start >= $maxItems) {
$empty['total_count'] = $totalCount;
$hasMore = count($mutuals) > $limit; return $empty;
if ($hasMore) {
$mutuals = array_slice($mutuals, 0, $limit);
} }
$nextCursor = $hasMore && ! empty($mutuals) ? end($mutuals) : null; $end = min($start + $limit, $maxItems);
$mutuals = Redis::zrevrange($mutualsKey, $start, $end);
$hasMore = count($mutuals) > $limit && ($start + $limit) < $maxItems;
$mutuals = array_slice($mutuals, 0, $limit);
$nextCursor = $hasMore && ! empty($mutuals) ? (int) end($mutuals) : null;
return [ return [
'data' => array_map('intval', $mutuals), 'data' => array_map('intval', $mutuals),
'has_more' => $hasMore, 'has_more' => $hasMore,
'next_cursor' => $nextCursor ? (int) $nextCursor : null, 'next_cursor' => $nextCursor,
'total_count' => Redis::zcard($mutualsKey), 'total_count' => $totalCount,
]; ];
} }
@ -376,12 +389,9 @@ class FollowerService
} }
} }
return [ $mutuals['data'] = $orderedProfiles;
'data' => $orderedProfiles,
'has_more' => $mutuals['has_more'], return $mutuals;
'next_cursor' => $mutuals['next_cursor'],
'total_count' => $mutuals['total_count'],
];
} }
public static function getMutualCount($profileId) public static function getMutualCount($profileId)

Loading…
Cancel
Save