Skip to content

Commit

Permalink
perf: eager-load votes (#109)
Browse files Browse the repository at this point in the history
* perf: eager-load votes
* Apply fixes from StyleCI
* fix: sum value
* fix: mostRelevantPost and update count action
  • Loading branch information
SychO9 authored Nov 11, 2023
1 parent 1d70769 commit 80e7499
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 23 deletions.
36 changes: 21 additions & 15 deletions extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,21 @@

new Extend\Locales(__DIR__.'/resources/locale'),

(new Extend\Model(User::class))
->belongsToMany('allVotes', User::class, 'user_id'),

(new Extend\Model(User::class))
->belongsToMany('ranks', Rank::class, 'rank_users'),

(new Extend\Model(Post::class))
->belongsToMany('votes', User::class, 'post_votes', 'post_id', 'user_id')
->relationship('upvotes', function (Post $post) {
return $post->belongsToMany(User::class, 'post_votes', 'post_id', 'user_id', null, null, 'upvotes')
->where('value', '>', 0);
return $post->votes()->where('value', '>', 0);
})
->relationship('downvotes', function (Post $post) {
return $post->belongsToMany(User::class, 'post_votes', 'post_id', 'user_id', null, null, 'upvotes')
->where('value', -1);
return $post->votes()->where('value', -1);
})
->relationship('actualvotes', function (Post $post) {
return $post->hasMany(Vote::class, 'post_id');
}),

(new Extend\Model(Post::class))
->belongsToMany('votes', User::class, 'post_votes', 'post_id', 'user_id'),

(new ExtensionSettings())
->setPrefix('fof-gamification.')
->addKeys([
Expand Down Expand Up @@ -155,27 +151,37 @@
->addInclude('ranks'),

(new Extend\ApiController(Controller\ShowDiscussionController::class))
->addInclude('posts.user.ranks'),
->addInclude('posts.user.ranks')
->loadWhere('posts.actualvotes', [LoadActorVoteRelationship::class, 'mutateRelation'])
->prepareDataForSerialization([LoadActorVoteRelationship::class, 'sumRelation']),

(new Extend\ApiController(Controller\ListDiscussionsController::class))
->addSortField('hotness')
->addSortField('votes'),
->addSortField('votes')
->loadWhere('firstPost.actualvotes', [LoadActorVoteRelationship::class, 'mutateRelation'])
->prepareDataForSerialization([LoadActorVoteRelationship::class, 'sumRelation']),

(new Extend\ApiController(Controller\ListPostsController::class))
->addInclude('user.ranks')
->addOptionalInclude(['upvotes', 'downvotes']),
->addOptionalInclude(['upvotes', 'downvotes'])
->loadWhere('actualvotes', [LoadActorVoteRelationship::class, 'mutateRelation'])
->prepareDataForSerialization([LoadActorVoteRelationship::class, 'sumRelation']),

(new Extend\ApiController(Controller\ShowPostController::class))
->addInclude('user.ranks')
->addOptionalInclude(['upvotes', 'downvotes']),
->addOptionalInclude(['upvotes', 'downvotes'])
->loadWhere('actualvotes', [LoadActorVoteRelationship::class, 'mutateRelation'])
->prepareDataForSerialization([LoadActorVoteRelationship::class, 'sumRelation']),

(new Extend\ApiController(Controller\CreatePostController::class))
->addInclude('user.ranks')
->addOptionalInclude(['upvotes', 'downvotes']),

(new Extend\ApiController(Controller\UpdatePostController::class))
->addInclude('user.ranks')
->addOptionalInclude(['upvotes', 'downvotes']),
->addOptionalInclude(['upvotes', 'downvotes'])
->loadWhere('actualvotes', [LoadActorVoteRelationship::class, 'mutateRelation'])
->prepareDataForSerialization([LoadActorVoteRelationship::class, 'sumRelation']),

(new Extend\ApiController(Controller\ShowForumController::class))
->addInclude('ranks'),
Expand Down
5 changes: 1 addition & 4 deletions src/AddDiscussionData.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ public function __invoke(BasicDiscussionSerializer $serializer, Discussion $disc
$actor = $serializer->getActor();

if (!$actor->isGuest() && $actor->exists && $post) {
$vote = Vote::query()->where([
'post_id' => $post->id,
'user_id' => $actor->id,
])->first(['value']);
$vote = $post->actualvotes->first();

$attributes['hasUpvoted'] = $vote && $vote->isUpvote();
$attributes['hasDownvoted'] = $vote && $vote->isDownvote();
Expand Down
4 changes: 2 additions & 2 deletions src/AddPostData.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function __invoke(PostSerializer $serializer, Post $post, array $attribut

if ($canSeeVotes) {
if ($actor->exists) {
$vote = Vote::query()->where(['post_id' => $post->id, 'user_id' => $actor->id])->first(['value']);
$vote = $post->actualvotes->first();

$attributes['hasUpvoted'] = $vote && $vote->isUpvote();
$attributes['hasDownvoted'] = $vote && $vote->isDownvote();
Expand All @@ -44,7 +44,7 @@ public function __invoke(PostSerializer $serializer, Post $post, array $attribut
$attributes['hasDownvoted'] = null;
}
$attributes['canSeeVotes'] = $canSeeVotes;
$attributes['votes'] = Vote::calculate(['post_id' => $post->id]);
$attributes['votes'] = $post->actualvotes_sum_value;
} else {
$attributes['votes'] = null;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Gambit/HotGambit.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function getGambitPattern()
/**
* @param SearchState $search
* @param array $matches
* @param $negate
* @param $negate
*/
protected function conditions(SearchState $search, array $matches, $negate)
{
Expand Down
52 changes: 52 additions & 0 deletions src/LoadActorVoteRelationship.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

/*
* This file is part of fof/gamification.
*
* Copyright (c) FriendsOfFlarum.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FoF\Gamification;

use Flarum\Discussion\Discussion;
use Flarum\Http\RequestUtil;
use Flarum\Post\Post;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Psr\Http\Message\ServerRequestInterface;

class LoadActorVoteRelationship
{
public static function mutateRelation(HasMany $query, ServerRequestInterface $request): HasMany
{
$actor = RequestUtil::getActor($request);

return $query
// So that we can tell if the current user has liked the post.
->where('user_id', $actor->id);
}

public static function sumRelation($controller, $data): void
{
$loadable = null;

if ($data instanceof Discussion) {
$loadable = $data->newCollection($data->posts)->filter(function ($post) {
return $post instanceof Post;
});
} elseif ($data instanceof Collection) {
$loadable = $data->map(function ($model) {
return $model instanceof Discussion ? ($model->mostRelevantPost ?? $model->firstPost) : $model;
});
} elseif ($data instanceof Post) {
$loadable = $data->newCollection([$data]);
}

if ($loadable) {
$loadable->loadSum('actualvotes', 'value');
}
}
}
2 changes: 1 addition & 1 deletion src/Search/HotFilterGambit.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ protected function sort(Builder $query, User $actor, bool $negate)
/**
* @param SearchState $search
* @param array $matches
* @param $negate
* @param $negate
*/
protected function conditions(SearchState $search, array $matches, $negate)
{
Expand Down

0 comments on commit 80e7499

Please sign in to comment.