Merge pull request #6054 from FinnStutzenstein/speedupPollStop

Speed up stopping a poll
This commit is contained in:
Emanuel Schütze 2021-05-06 17:49:42 +02:00 committed by GitHub
commit 964a41386d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 12 deletions

View File

@ -264,18 +264,25 @@ class BasePoll(models.Model):
self.is_pseudoanonymized = False self.is_pseudoanonymized = False
self.save() self.save()
def calculate_votes(self): def calculate_votes(self, all_voted_users=None):
if self.type != BasePoll.TYPE_ANALOG: if self.type == BasePoll.TYPE_ANALOG:
self.votescast = self.voted.count() return
if all_voted_users is None:
all_voted_users = self.voted.all()
self.votescast = len(all_voted_users)
if config["users_activate_vote_weight"]: if config["users_activate_vote_weight"]:
self.votesvalid = sum(self.voted.values_list("vote_weight", flat=True)) self.votesvalid = sum(user.vote_weight for user in all_voted_users)
else: else:
self.votesvalid = self.votescast self.votesvalid = self.votescast
self.votesinvalid = Decimal(0) self.votesinvalid = Decimal(0)
def calculate_entitled_users(self): def calculate_entitled_users(self, all_voted_users=None):
entitled_users = [] entitled_users = []
entitled_users_ids = set() entitled_users_ids = set()
if all_voted_users is None:
all_voted_users = self.voted.all()
for group in self.groups.all(): for group in self.groups.all():
for user in group.user_set.all(): for user in group.user_set.all():
if ( if (
@ -286,7 +293,7 @@ class BasePoll(models.Model):
entitled_users.append( entitled_users.append(
{ {
"user_id": user.id, "user_id": user.id,
"voted": user in self.voted.all(), "voted": user in all_voted_users,
"vote_delegated_to_id": user.vote_delegated_to_id, "vote_delegated_to_id": user.vote_delegated_to_id,
} }
) )
@ -296,7 +303,8 @@ class BasePoll(models.Model):
""" """
Saves a snapshot of the current voted users into the relevant fields and stops the poll. Saves a snapshot of the current voted users into the relevant fields and stops the poll.
""" """
self.calculate_votes() all_voted_users = self.voted.all() # just fetch this once from the database now
self.calculate_entitled_users() self.calculate_votes(all_voted_users)
self.calculate_entitled_users(all_voted_users)
self.state = self.STATE_FINISHED self.state = self.STATE_FINISHED
self.save() self.save()

View File

@ -1211,6 +1211,31 @@ class StopMotionPoll(TestCase):
], ],
) )
def test_stop_poll_multiple_users_database_query_count(self):
"""
The code in BasePoll.stop() should not make too much queries.
"""
self.setup_entitled_users()
expected = []
for _ in range(10):
user, _ = self.create_user()
user.is_present = True
user.vote_delegated_to = self.admin
user.save()
user.groups.add(self.group)
expected.append(
{
"user_id": user.id,
"voted": False,
"vote_delegated_to_id": self.admin.id,
}
)
self.admin.is_present = False
self.admin.save()
config["users_activate_vote_weight"] = True
self.assertEqual(count_queries(self.poll.stop)(), 13)
self.assertEqual(MotionPoll.objects.get().entitled_users_at_stop, expected)
def test_stop_poll_assert_no_duplicate_entitled_users(self): def test_stop_poll_assert_no_duplicate_entitled_users(self):
self.setup_entitled_users() self.setup_entitled_users()
delegate_group = get_group_model().objects.get(pk=GROUP_DELEGATE_PK) delegate_group = get_group_model().objects.get(pk=GROUP_DELEGATE_PK)