Speed up stopping a poll

Reduced the amount of queries in BasePoll.stop from 4+<amount entitled
users> to 3.
This commit is contained in:
Finn Stutzenstein 2021-05-06 16:06:52 +02:00 committed by Joshua Sangmeister
parent 2a7b55f11e
commit 1e78f2a534
2 changed files with 45 additions and 12 deletions

View File

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