fix(FastAPI): voted/notified query efficiency

Previously, we were running a single ORM query for every single package
to check for its voted or notified states. Now, we perform a single
ORM query for each of the set of voted or notified packages in
relation with the request user.

This improves performance drastically at the expense of some
manual code additions and set-dependency; i.e. we add a bit
more complexity and roundabout way of getting our data.

Closes: https://gitlab.archlinux.org/archlinux/aurweb/-/issues/102

Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
Kevin Morris 2021-09-18 23:30:51 -07:00
parent fd9b07c429
commit 4de18d8134
No known key found for this signature in database
GPG key ID: F7E46DED420788F3
5 changed files with 126 additions and 11 deletions

View file

@ -1,3 +1,5 @@
from datetime import datetime
import pytest
from fastapi.testclient import TestClient
@ -7,6 +9,8 @@ from aurweb.models.account_type import USER_ID, AccountType
from aurweb.models.official_provider import OFFICIAL_BASE, OfficialProvider
from aurweb.models.package import Package
from aurweb.models.package_base import PackageBase
from aurweb.models.package_notification import PackageNotification
from aurweb.models.package_vote import PackageVote
from aurweb.models.user import User
from aurweb.packages import util
from aurweb.redis import kill_redis
@ -19,6 +23,8 @@ def setup():
User.__tablename__,
Package.__tablename__,
PackageBase.__tablename__,
PackageVote.__tablename__,
PackageNotification.__tablename__,
OfficialProvider.__tablename__
)
@ -71,3 +77,24 @@ def test_updated_packages(maintainer: User, package: Package):
assert util.updated_packages(1, 0) == [expected]
assert util.updated_packages(1, 600) == [expected]
kill_redis() # Kill it again, in case other tests use a real instance.
def test_query_voted(maintainer: User, package: Package):
now = int(datetime.utcnow().timestamp())
with db.begin():
db.create(PackageVote, User=maintainer, VoteTS=now,
PackageBase=package.PackageBase)
query = db.query(Package).filter(Package.ID == package.ID).all()
query_voted = util.query_voted(query, maintainer)
assert query_voted[package.PackageBase.ID]
def test_query_notified(maintainer: User, package: Package):
with db.begin():
db.create(PackageNotification, User=maintainer,
PackageBase=package.PackageBase)
query = db.query(Package).filter(Package.ID == package.ID).all()
query_notified = util.query_notified(query, maintainer)
assert query_notified[package.PackageBase.ID]