Skip to content

Commit

Permalink
Merge pull request #42 from devinmatte/performance
Browse files Browse the repository at this point in the history
Aggressive Caching
  • Loading branch information
zedoax authored Sep 4, 2018
2 parents 8d8830b + 2ddcb1d commit 2150eff
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 116 deletions.
70 changes: 17 additions & 53 deletions packet/ldap.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from functools import lru_cache

import ldap

from packet import _ldap


@lru_cache(maxsize=1024)
def _ldap_get_group_members(group):
return _ldap.get_group(group).get_members()


@lru_cache(maxsize=2048)
def _ldap_is_member_of_group(member, group):
group_list = member.get("memberOf")
for group_dn in group_list:
Expand Down Expand Up @@ -48,16 +48,6 @@ def ldap_get_onfloor_members():
return _ldap_get_group_members("onfloor")


@lru_cache(maxsize=1024)
def ldap_get_current_students():
return _ldap_get_group_members("current_student")


@lru_cache(maxsize=1024)
def ldap_get_all_members():
return _ldap_get_group_members("member")


@lru_cache(maxsize=1024)
def ldap_get_groups(account):
group_list = account.get("memberOf")
Expand All @@ -68,17 +58,6 @@ def ldap_get_groups(account):
return groups


@lru_cache(maxsize=1024)
def ldap_get_group_desc(group):
con = _ldap.get_con()
results = con.search_s(
"cn=groups,cn=accounts,dc=csh,dc=rit,dc=edu",
ldap.SCOPE_SUBTREE,
"(cn=%s)" % group,
['description'])
return results[0][1]['description'][0].decode('utf-8')


@lru_cache(maxsize=1024)
def ldap_get_eboard():
members = _ldap_get_group_members("eboard-chairman") + _ldap_get_group_members("eboard-evaluations"
Expand All @@ -90,6 +69,7 @@ def ldap_get_eboard():
return members


@lru_cache(maxsize=2048)
def ldap_get_live_onfloor():
"""
:return: All upperclassmen who live on floor and are not eboard
Expand All @@ -101,67 +81,51 @@ def ldap_get_live_onfloor():
members.append(member)
return members


# Status checkers

@lru_cache(maxsize=1024)
def ldap_is_eval_director(account):
return _ldap_is_member_of_directorship(account, 'evaluations')


@lru_cache(maxsize=1024)
def ldap_is_active(account):
return _ldap_is_member_of_group(account, 'active')


@lru_cache(maxsize=1024)
def ldap_is_alumni(account):
# If the user is not active, they are an alumni.
return not _ldap_is_member_of_group(account, 'active')


@lru_cache(maxsize=1024)
def ldap_is_eboard(account):
return _ldap_is_member_of_group(account, 'eboard')


@lru_cache(maxsize=1024)
def ldap_is_rtp(account):
return _ldap_is_member_of_group(account, 'rtp')


@lru_cache(maxsize=1024)
def ldap_is_intromember(account):
return _ldap_is_member_of_group(account, 'intromembers')


@lru_cache(maxsize=1024)
def ldap_is_onfloor(account):
return _ldap_is_member_of_group(account, 'onfloor')


@lru_cache(maxsize=1024)
def ldap_is_current_student(account):
return _ldap_is_member_of_group(account, 'current_student')


# Directorships

def ldap_is_financial_director(account):
return _ldap_is_member_of_directorship(account, 'financial')


def ldap_is_eval_director(account):
return _ldap_is_member_of_directorship(account, 'evaluations')


def ldap_is_chairman(account):
return _ldap_is_member_of_directorship(account, 'chairman')


def ldap_is_history(account):
return _ldap_is_member_of_directorship(account, 'history')


def ldap_is_imps(account):
return _ldap_is_member_of_directorship(account, 'imps')


def ldap_is_social(account):
return _ldap_is_member_of_directorship(account, 'Social')


def ldap_is_rd(account):
return _ldap_is_member_of_directorship(account, 'research')


@lru_cache(maxsize=1024)
def ldap_get_roomnumber(account):
try:
return account.roomNumber
Expand Down
3 changes: 3 additions & 0 deletions packet/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"""

from datetime import datetime
from functools import lru_cache

from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, Boolean
from sqlalchemy.orm import relationship

Expand Down Expand Up @@ -47,6 +49,7 @@ class Packet(db.Model):
def is_open(self):
return self.start < datetime.now() < self.end

@lru_cache(maxsize=1024)
def signatures_required(self):
eboard = UpperSignature.query.filter_by(eboard=True).count()
return {'eboard': eboard,
Expand Down
24 changes: 24 additions & 0 deletions packet/packet.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import copy
from functools import lru_cache

from packet.ldap import ldap_get_member, ldap_is_intromember
from .models import Freshman, UpperSignature, FreshSignature, MiscSignature, db

Expand Down Expand Up @@ -32,9 +35,15 @@ def sign(signer_username, freshman_username):
db.session.add(MiscSignature(packet=packet, member=signer_username))
db.session.commit()

# Clear functions that read signatures cache
get_number_signed.cache_clear()
get_signatures.cache_clear()
get_upperclassmen_percent.cache_clear()

return True


@lru_cache(maxsize=2048)
def get_signatures(freshman_username):
packet = Freshman.query.filter_by(rit_username=freshman_username).first().current_packet()
eboard = UpperSignature.query.filter_by(packet_id=packet.id, eboard=True).order_by(UpperSignature.signed.desc())
Expand All @@ -48,9 +57,24 @@ def get_signatures(freshman_username):
'misc': misc_signatures}


@lru_cache(maxsize=2048)
def get_number_signed(freshman_username):
return Freshman.query.filter_by(rit_username=freshman_username).first().current_packet().signatures_received()


@lru_cache(maxsize=4096)
def get_number_required(freshman_username):
return Freshman.query.filter_by(rit_username=freshman_username).first().current_packet().signatures_required()


@lru_cache(maxsize=2048)
def get_upperclassmen_percent(uid):
upperclassmen_required = copy.deepcopy(get_number_required(uid))
del upperclassmen_required['freshmen']
upperclassmen_required = sum(upperclassmen_required.values())

upperclassmen_signature = copy.deepcopy(get_number_signed(uid))
del upperclassmen_signature['freshmen']
upperclassmen_signature = sum(upperclassmen_signature.values())

return upperclassmen_signature / upperclassmen_required * 100
28 changes: 10 additions & 18 deletions packet/routes/shared.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from flask import render_template
from datetime import datetime
from itertools import chain

from flask import render_template

from packet import auth, app
from packet.models import Freshman, Packet
from packet.packet import get_signatures, get_number_required, get_number_signed
from packet.packet import get_signatures, get_number_required, get_number_signed, get_upperclassmen_percent
from packet.utils import before_request, signed_packet


Expand All @@ -13,21 +14,12 @@
@before_request
def freshman_packet(uid, info=None):
freshman = Freshman.query.filter_by(rit_username=uid).first()
upperclassmen_percent = get_upperclassmen_percent(uid)
signatures = get_signatures(uid)
signed_dict = get_number_signed(uid)
required = sum(get_number_required(uid).values())
signed = sum(signed_dict.values())

upperclassmen_required = get_number_required(uid)
del upperclassmen_required['freshmen']
upperclassmen_required = sum(upperclassmen_required.values())

upperclassmen_signature = get_number_signed(uid)
del upperclassmen_signature['freshmen']
upperclassmen_signature = sum(upperclassmen_signature.values())

upperclassmen_percent = upperclassmen_signature / upperclassmen_required * 100

packet_signed = signed_packet(info['uid'], uid)
return render_template("packet.html", info=info, signatures=signatures, uid=uid, required=required, signed=signed,
freshman=freshman, packet_signed=packet_signed, upperclassmen_percent=upperclassmen_percent,
Expand All @@ -38,12 +30,12 @@ def freshman_packet(uid, info=None):
@auth.oidc_auth
@before_request
def packets(info=None):
packets = Packet.query.filter(Packet.end > datetime.now()).filter(Packet.start < datetime.now()).all()
open_packets = Packet.query.filter(Packet.end > datetime.now()).filter(Packet.start < datetime.now()).all()

# Add the did_sign flag
if app.config["REALM"] == "csh":
# User is an upperclassman
for packet in packets:
for packet in open_packets:
packet.did_sign = False
packet.total_signatures = sum(packet.signatures_received().values())
packet.required_signatures = sum(packet.signatures_required().values())
Expand All @@ -54,7 +46,7 @@ def packets(info=None):
break
else:
# User is a freshman
for packet in packets:
for packet in open_packets:
packet.did_sign = False
packet.total_signatures = sum(packet.signatures_received().values())
packet.required_signatures = sum(packet.signatures_required().values())
Expand All @@ -64,7 +56,7 @@ def packets(info=None):
packet.did_sign = True
break

packets.sort(key=lambda x: sum(x.signatures_received().values()), reverse=True)
packets.sort(key=lambda x: x.did_sign, reverse=True)
open_packets.sort(key=lambda x: sum(x.signatures_received().values()), reverse=True)
open_packets.sort(key=lambda x: x.did_sign, reverse=True)

return render_template("active_packets.html", info=info, packets=packets)
return render_template("active_packets.html", info=info, packets=open_packets)
2 changes: 1 addition & 1 deletion packet/templates/active_packets.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ <h3 class="page-title">Active Packets</h3>
alt="{{ packet.freshman.name }}"
src="https://www.gravatar.com/avatar/freshmen?d=mp&f=y"
width="25"
height="25"/> {{ get_freshman_name(packet.freshman.rit_username) }}
height="25"/> {{ packet.freshman.name }} ({{ packet.freshman.rit_username }})
</a>
</td>
<td>
Expand Down
2 changes: 1 addition & 1 deletion packet/templates/packet.html
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ <h5>Upperclassmen Score</h5>
<img class="eval-user-img" alt="{{ m.freshman.rit_username }}"
src="https://www.gravatar.com/avatar/freshmen?d=mp&f=y"
width="25"
height="25"/> {{ get_freshman_name(m.freshman.rit_username) }}
height="25"/> {{ m.freshman.name }} ({{ m.freshman.rit_username }})
</a>
</td>
<td width="15%">
Expand Down
2 changes: 1 addition & 1 deletion packet/templates/upperclassman.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ <h3 class="page-title">{{ get_display_name(member) }}</h3>
alt="{{ m.packet.freshman.name }}"
src="https://profiles.csh.rit.edu/image/{{ m.packet.freshman.rit_username }}"
width="25"
height="25"/> {{ get_freshman_name(m.packet.freshman.name) }}
height="25"/> {{ m.packet.freshman.name }} ({{ m.packet.freshman.rit_username }})
</a>
</td>
<td width="15%">
Expand Down
45 changes: 3 additions & 42 deletions packet/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,55 +45,22 @@ def wrapped_function(*args, **kwargs):
return wrapped_function


@lru_cache(maxsize=2048)
def get_member_info(uid):
account = ldap_get_member(uid)

member_info = {
"user_obj": account,
"group_list": ldap_get_groups(account),
"uid": account.uid,
"ritUid": parse_rit_uid(account.ritDn),
"name": account.cn,
"active": ldap_is_active(account),
"onfloor": ldap_is_onfloor(account),
"room": ldap_get_roomnumber(account),
"hp": account.housingPoints,
"plex": account.plex,
"rn": ldap_get_roomnumber(account),
"birthday": parse_date(account.birthday),
"memberSince": parse_date(account.memberSince),
"lastlogin": parse_date(account.krblastsuccessfulauth),
"year": parse_account_year(account.memberSince)
}
return member_info


def parse_date(date):
if date:
year = date[0:4]
month = date[4:6]
day = date[6:8]
return month + "-" + day + "-" + year
return False


def parse_rit_uid(dn):
if dn:
return dn.split(",")[0][4:]

return None


def parse_account_year(date):
if date:
year = int(date[0:4])
month = int(date[4:6])
if month <= 8:
year = year - 1
return year
return None


@lru_cache(maxsize=2048)
def is_on_floor(uid):
return (Freshman.query.filter_by(rit_username=uid)).first().onfloor
Expand All @@ -118,18 +85,12 @@ def signed_packet(signer, freshman):
@app.context_processor
def utility_processor():
# pylint: disable=bare-except
@lru_cache(maxsize=4096)
def get_display_name(username):
try:
member = ldap_get_member(username)
return member.cn + " (" + member.uid + ")"
except:
return username

def get_freshman_name(username):
try:
freshman = Freshman.query.filter_by(rit_username=username).first()
return freshman.name + " (" + freshman.rit_username + ")"
except:
return username

return dict(get_display_name=get_display_name, get_freshman_name=get_freshman_name)
return dict(get_display_name=get_display_name)

0 comments on commit 2150eff

Please sign in to comment.