perf: optimize away special privilege requests by lazy loading

This commit is contained in:
Lephe 2022-05-12 19:19:17 +01:00
parent 1040d57506
commit 7d9e897ae9
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
4 changed files with 48 additions and 8 deletions

View File

@ -16,16 +16,18 @@ class SpecialPrivilege(db.Model):
id = db.Column(db.Integer, primary_key=True)
# Member that is granted the privilege
mid = db.Column(db.Integer, db.ForeignKey('member.id'), index=True)
member_id = db.Column(db.Integer, db.ForeignKey('member.id'), index=True)
member = db.relationship('Member', backref="special_privs",
foreign_keys=member_id)
# Privilege name
priv = db.Column(db.String(64))
def __init__(self, member, priv):
self.mid = member.id
self.member = member
self.priv = priv
def __repr__(self):
return f'<Privilege: {self.priv} of member #{self.mid}>'
return f'<Privilege: {self.priv} of member #{self.member_id}>'
# Group: User group, corresponds to a community role and a set of privileges

View File

@ -139,6 +139,7 @@ class Member(User):
# Other fields populated automatically through relations:
# <special_privs> List of special privileges
# <notifications> List of unseen notifications (of type Notification)
# <polls> Polls created by the member (of class Poll)
@ -194,7 +195,7 @@ class Member(User):
Deletes the user, but not the posts; use either transfer_posts() or
delete_posts() before calling this.
"""
for sp in SpecialPrivilege.query.filter_by(mid=self.id).all():
for sp in self.special_privs:
db.session.delete(sp)
self.trophies = []
@ -207,7 +208,7 @@ class Member(User):
def priv(self, priv):
"""Check whether the member has the specified privilege."""
if SpecialPrivilege.query.filter_by(mid=self.id, priv=priv).first():
if priv in self.special_privs:
return True
return db.session.query(Group, GroupPrivilege).filter(
Group.id.in_([g.id for g in self.groups]),
@ -216,8 +217,7 @@ class Member(User):
def special_privileges(self):
"""List member's special privileges."""
sp = SpecialPrivilege.query.filter_by(mid=self.id).all()
return sorted(row.priv for row in sp)
return sorted(self.special_privs)
def can_access_forum(self, forum):
"""Whether this member can read the forum's contents."""

View File

@ -15,7 +15,7 @@ def adm_groups():
# Users with either groups or special privileges
users_groups = Member.query.join(GroupMember)
users_special = Member.query \
.join(SpecialPrivilege, Member.id == SpecialPrivilege.mid)
.join(SpecialPrivilege, Member.id == SpecialPrivilege.member_id)
users = users_groups.union(users_special)
users = sorted(users, key = lambda x: x.name)

View File

@ -0,0 +1,38 @@
"""special privileges as a relationship
Revision ID: 44fbbb1fd537
Revises: 72df33816b21
Create Date: 2022-05-12 19:15:15.592896
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '44fbbb1fd537'
down_revision = '72df33816b21'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('special_privilege', sa.Column('member_id', sa.Integer(), nullable=True))
op.drop_index('ix_special_privilege_mid', table_name='special_privilege')
op.create_index(op.f('ix_special_privilege_member_id'), 'special_privilege', ['member_id'], unique=False)
op.drop_constraint('special_privilege_mid_fkey', 'special_privilege', type_='foreignkey')
op.create_foreign_key(None, 'special_privilege', 'member', ['member_id'], ['id'])
op.drop_column('special_privilege', 'mid')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('special_privilege', sa.Column('mid', sa.INTEGER(), autoincrement=False, nullable=True))
op.drop_constraint(None, 'special_privilege', type_='foreignkey')
op.create_foreign_key('special_privilege_mid_fkey', 'special_privilege', 'member', ['mid'], ['id'])
op.drop_index(op.f('ix_special_privilege_member_id'), table_name='special_privilege')
op.create_index('ix_special_privilege_mid', 'special_privilege', ['mid'], unique=False)
op.drop_column('special_privilege', 'member_id')
# ### end Alembic commands ###