Skip to content

Commit

Permalink
perf(backend): Remove N+1 on the parameters endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
barnslig committed Jan 19, 2022
1 parent 30a4640 commit 2bbb028
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 11 deletions.
15 changes: 5 additions & 10 deletions backend/dpt_app/trails/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,11 @@ class Meta:
@property
@admin.display(description=_("Maximum Game Duration"))
def max_clock_duration(self):
"""Get the maximum clock duration, in seconds"""
return Parameter.max_clock_duration(self)
"""Get the maximum clock duration in seconds at which the first parameter is zero"""
query = self.parameter.annotate(
dur_when_zero=-1 * (F('initial_value') + F('value')) / ((F('game__clock_speed') / F('game__clock_unit')) * F('rate')))

return query.aggregate(Min('dur_when_zero'))['dur_when_zero__min'] or 0

@property
@admin.display(description=_("Total Game Duration"))
Expand Down Expand Up @@ -195,14 +198,6 @@ class Meta:
verbose_name=_("Game")
)

@staticmethod
def max_clock_duration(game: Game):
"""Get the maximum game clock duration in seconds at which the first parameter is zero"""
query = Parameter.objects.filter(game=game).annotate(
dur_when_zero=-1 * (F('initial_value') + F('value')) / ((F('game__clock_speed') / F('game__clock_unit')) * F('rate')))

return query.aggregate(Min('dur_when_zero'))['dur_when_zero__min'] or 0

def value_at(self, clock_duration):
"""Get the parameter value at a specific game clock duration"""
value = round((self.initial_value + self.value) + clock_duration
Expand Down
8 changes: 7 additions & 1 deletion backend/dpt_app/trails/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ def get_bearer(request):


def func_parameter_get(game, player):
# By retrieving the duration only once, then call `.value_at(dur)`
# on every parameter instead of `.current_value`, we only need a
# single SQL query for the duration instead of N, where N is the
# number of parameters.
dur = game.total_clock_duration

response = []
for parameter in game.parameter.all():
response.append(
Expand All @@ -234,7 +240,7 @@ def func_parameter_get(game, player):
"id": parameter.name,
"attributes": {
"scope": parameter.scope,
"value": parameter.current_value,
"value": parameter.value_at(dur),
"rate": parameter.rate,
"min": parameter.min_value,
"max": parameter.max_value
Expand Down

0 comments on commit 2bbb028

Please sign in to comment.