Skip to content

Commit 04db772

Browse files
Make not slow (#456)
* bump stuff * add type hints to ldap.py * more sane ldap queries * improved gatekeep calculations * improve housing queue calculations * reorganize directorships calculations * fix calculations and remove old function * fix linting * oops fix typo * squish lines together * speedup spring evals page * More spring evals speedup * fix linting * speed up intro evals * profiling documentation * added profiling env variable * oops i missed a part --------- Co-authored-by: Noah Hanford (spaced) <spaced@csh.rit.edu>
1 parent 1946a96 commit 04db772

File tree

12 files changed

+479
-270
lines changed

12 files changed

+479
-270
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ This will run the asset pipeline, start the Python server, and start BrowserSync
6161

6262
To add new dependencies, add them to `requirements.in` and then run `pip-compile requirements.in` to produce a new locked `requirements.txt`. Do not edit `requirements.txt` directly as it will be overwritten by future PRs.
6363

64+
after app initialization
65+
6466
### Database Migrations
6567

6668
If the database schema is changed after initializing the database, you must migrate it to the new schema by running:

conditional/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import sentry_sdk
1414
from sentry_sdk.integrations.flask import FlaskIntegration
1515
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
16+
from werkzeug.middleware.profiler import ProfilerMiddleware
1617

1718
app = Flask(__name__)
1819
gzip = Gzip(app)
@@ -29,6 +30,12 @@
2930
db = SQLAlchemy(app)
3031
migrate = Migrate(app, db)
3132

33+
if app.config['PROFILING']:
34+
app.wsgi_app = ProfilerMiddleware(
35+
app.wsgi_app,
36+
restrictions=[30]
37+
)
38+
3239
# Sentry setup
3340
sentry_sdk.init(
3441
dsn=app.config['SENTRY_DSN'],

conditional/blueprints/dashboard.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def display_dashboard(user_dict=None):
3636
log.info('display dashboard')
3737

3838
# Get the list of voting members.
39+
3940
can_vote = get_voting_members()
4041

4142
data = {}
@@ -56,7 +57,7 @@ def display_dashboard(user_dict=None):
5657
spring = {}
5758
c_meetings = get_cm(user_dict['account'])
5859
spring['committee_meetings'] = len(c_meetings)
59-
spring['req_meetings'] = req_cm(user_dict['account'])
60+
spring['req_meetings'] = req_cm(user_dict['account'].uid)
6061
h_meetings = [(m.meeting_id, m.attendance_status) for m in get_hm(user_dict['account'])]
6162
spring['hm_missed'] = len([h for h in h_meetings if h[1] == "Absent"])
6263
eval_entry = SpringEval.query.filter(SpringEval.uid == user_dict['account'].uid,

conditional/blueprints/intro_evals.py

Lines changed: 168 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import structlog
44
from flask import Blueprint, request
5+
from sqlalchemy import func
56

67
from conditional import start_of_year, auth
78
from conditional.models.models import CommitteeMeeting
@@ -11,89 +12,182 @@
1112
from conditional.models.models import FreshmanHouseMeetingAttendance
1213
from conditional.models.models import FreshmanSeminarAttendance
1314
from conditional.models.models import HouseMeeting
15+
from conditional.models.models import MemberCommitteeAttendance
1416
from conditional.models.models import MemberHouseMeetingAttendance
1517
from conditional.models.models import MemberSeminarAttendance
1618
from conditional.models.models import TechnicalSeminar
1719
from conditional.util.auth import get_user
1820
from conditional.util.flask import render_template
1921
from conditional.util.ldap import ldap_get_intro_members
20-
from conditional.util.member import get_cm, get_hm
2122

2223
intro_evals_bp = Blueprint('intro_evals_bp', __name__)
2324

2425
logger = structlog.get_logger()
2526

26-
27-
@intro_evals_bp.route('/intro_evals/')
28-
@auth.oidc_auth("default")
29-
@get_user
30-
def display_intro_evals(internal=False, user_dict=None):
31-
log = logger.new(request=request, auth_dict=user_dict)
32-
log.info('Display Intro Evals Listing')
33-
34-
# get user data
35-
def get_fid_cm_count(member_id):
36-
return len([a for a in FreshmanCommitteeAttendance.query.filter(
37-
FreshmanCommitteeAttendance.fid == member_id)
38-
if CommitteeMeeting.query.filter(CommitteeMeeting.id == a.meeting_id).first().approved])
39-
40-
members = ldap_get_intro_members()
41-
42-
ie_members = []
27+
def get_intro_members_without_accounts():
28+
freshman_cm_count = dict([tuple(row) for row in FreshmanCommitteeAttendance.query.join(
29+
CommitteeMeeting,
30+
FreshmanCommitteeAttendance.meeting_id == CommitteeMeeting.id
31+
).with_entities(
32+
FreshmanCommitteeAttendance.fid,
33+
CommitteeMeeting.timestamp,
34+
CommitteeMeeting.approved,
35+
).filter(
36+
CommitteeMeeting.approved,
37+
CommitteeMeeting.timestamp >= start_of_year()
38+
).with_entities(
39+
FreshmanCommitteeAttendance.fid,
40+
func.count(FreshmanCommitteeAttendance.fid) #pylint: disable=not-callable
41+
).group_by(
42+
FreshmanCommitteeAttendance.fid
43+
).all()])
44+
45+
freshman_hm_missed = dict([tuple(row) for row in FreshmanHouseMeetingAttendance.query.join(
46+
HouseMeeting,
47+
FreshmanHouseMeetingAttendance.meeting_id == HouseMeeting.id
48+
).filter(
49+
HouseMeeting.date >= start_of_year(),
50+
FreshmanHouseMeetingAttendance.attendance_status == 'Absent'
51+
).with_entities(
52+
FreshmanHouseMeetingAttendance.fid,
53+
func.count(FreshmanHouseMeetingAttendance.fid) #pylint: disable=not-callable
54+
).group_by(
55+
FreshmanHouseMeetingAttendance.fid
56+
).all()])
57+
58+
freshman_ts_attendance_query = FreshmanSeminarAttendance.query.join(
59+
TechnicalSeminar,
60+
FreshmanSeminarAttendance.seminar_id == TechnicalSeminar.id
61+
).with_entities(
62+
FreshmanSeminarAttendance.fid,
63+
TechnicalSeminar.timestamp,
64+
TechnicalSeminar.approved
65+
).filter(
66+
TechnicalSeminar.approved,
67+
TechnicalSeminar.timestamp >= start_of_year()
68+
).with_entities(
69+
FreshmanSeminarAttendance.fid,
70+
TechnicalSeminar.name
71+
).all()
72+
73+
freshman_ts_attendance_dict = {}
74+
75+
for row in freshman_ts_attendance_query:
76+
if not row[0] in freshman_ts_attendance_dict:
77+
freshman_ts_attendance_dict[row[0]] = []
78+
79+
freshman_ts_attendance_dict[row[0]].append(row[1])
4380

4481
# freshmen who don't have accounts
45-
fids = list(FreshmanAccount.query.filter(
82+
freshman_accounts = list(FreshmanAccount.query.filter(
4683
FreshmanAccount.eval_date > start_of_year(),
4784
FreshmanAccount.eval_date > datetime.now()))
4885

49-
for fid in fids:
50-
h_meetings = [m.meeting_id for m in
51-
FreshmanHouseMeetingAttendance.query.filter(
52-
FreshmanHouseMeetingAttendance.fid == fid.id
53-
).filter(
54-
FreshmanHouseMeetingAttendance.attendance_status == "Absent"
55-
)]
86+
ie_members = []
5687

57-
if fid.signatures_missed is None:
88+
for freshman_account in freshman_accounts:
89+
missed_hms = []
90+
if freshman_hm_missed.get(freshman_account.id, 0) != 0:
91+
missed_hms = FreshmanHouseMeetingAttendance.query.join(
92+
HouseMeeting,
93+
FreshmanHouseMeetingAttendance.meeting_id == HouseMeeting.id
94+
).filter(
95+
HouseMeeting.date >= start_of_year(), # TODO: this needs to be fixed
96+
FreshmanHouseMeetingAttendance.attendance_status == 'Absent',
97+
FreshmanHouseMeetingAttendance.fid == freshman_account.id,
98+
).with_entities(
99+
func.array_agg(HouseMeeting.date)
100+
).scalar()
101+
102+
if freshman_account.signatures_missed is None:
58103
signatures_missed = -1
59104
else:
60-
signatures_missed = fid.signatures_missed
105+
signatures_missed = freshman_account.signatures_missed
106+
107+
cms_attended = freshman_cm_count.get(freshman_account.id, 0)
61108

62109
freshman = {
63-
'name': fid.name,
64-
'uid': fid.id,
65-
'eval_date': fid.eval_date.strftime("%Y-%m-%d"),
110+
'name': freshman_account.name,
111+
'uid': freshman_account.id,
112+
'eval_date': freshman_account.eval_date.strftime("%Y-%m-%d"),
66113
'signatures_missed': signatures_missed,
67-
'committee_meetings': get_fid_cm_count(fid.id),
68-
'committee_meetings_passed': get_fid_cm_count(fid.id) >= 6,
69-
'house_meetings_missed':
70-
[
71-
{
72-
"date": m.date.strftime("%Y-%m-%d"),
73-
"reason":
74-
FreshmanHouseMeetingAttendance.query.filter(
75-
FreshmanHouseMeetingAttendance.fid == fid.id).filter(
76-
FreshmanHouseMeetingAttendance.meeting_id == m.id).first().excuse
77-
}
78-
for m in HouseMeeting.query.filter(
79-
HouseMeeting.id.in_(h_meetings)
80-
)
81-
],
82-
'technical_seminars':
83-
[s.name for s in TechnicalSeminar.query.filter(
84-
TechnicalSeminar.id.in_(
85-
[a.seminar_id for a in FreshmanSeminarAttendance.query.filter(
86-
FreshmanSeminarAttendance.fid == fid.id)
87-
if TechnicalSeminar.query.filter(TechnicalSeminar.id == a.seminar_id).first().approved]
88-
))
89-
],
114+
'committee_meetings': cms_attended,
115+
'committee_meetings_passed': cms_attended >= 6,
116+
'house_meetings_missed': missed_hms,
117+
'technical_seminars': freshman_ts_attendance_dict.get(freshman_account.id, []),
90118
'social_events': '',
91119
'comments': "",
92120
'ldap_account': False,
93121
'status': "Pending"
94122
}
95123
ie_members.append(freshman)
96124

125+
return ie_members
126+
127+
@intro_evals_bp.route('/intro_evals/')
128+
@auth.oidc_auth("default")
129+
@get_user
130+
def display_intro_evals(internal=False, user_dict=None):
131+
log = logger.new(request=request, auth_dict=user_dict)
132+
log.info('Display Intro Evals Listing')
133+
134+
members = ldap_get_intro_members()
135+
136+
ie_members = get_intro_members_without_accounts()
137+
138+
account_cm_count = dict([tuple(row) for row in MemberCommitteeAttendance.query.join(
139+
CommitteeMeeting,
140+
MemberCommitteeAttendance.meeting_id == CommitteeMeeting.id
141+
).with_entities(
142+
MemberCommitteeAttendance.uid,
143+
CommitteeMeeting.timestamp,
144+
CommitteeMeeting.approved,
145+
).filter(
146+
CommitteeMeeting.approved,
147+
CommitteeMeeting.timestamp >= start_of_year()
148+
).with_entities(
149+
MemberCommitteeAttendance.uid,
150+
func.count(MemberCommitteeAttendance.uid) #pylint: disable=not-callable
151+
).group_by(
152+
MemberCommitteeAttendance.uid
153+
).all()])
154+
155+
account_hm_missed = dict([tuple(row) for row in MemberHouseMeetingAttendance.query.join(
156+
HouseMeeting,
157+
MemberHouseMeetingAttendance.meeting_id == HouseMeeting.id
158+
).filter(
159+
HouseMeeting.date >= start_of_year(),
160+
MemberHouseMeetingAttendance.attendance_status == 'Absent'
161+
).with_entities(
162+
MemberHouseMeetingAttendance.uid,
163+
func.count(MemberHouseMeetingAttendance.uid) #pylint: disable=not-callable
164+
).group_by(
165+
MemberHouseMeetingAttendance.uid
166+
).all()])
167+
168+
account_ts_attendance_query = MemberSeminarAttendance.query.join(
169+
TechnicalSeminar,
170+
MemberSeminarAttendance.seminar_id == TechnicalSeminar.id
171+
).with_entities(
172+
MemberSeminarAttendance.uid,
173+
TechnicalSeminar.timestamp,
174+
TechnicalSeminar.approved
175+
).filter(
176+
TechnicalSeminar.approved,
177+
TechnicalSeminar.timestamp >= start_of_year()
178+
).with_entities(
179+
MemberSeminarAttendance.uid,
180+
TechnicalSeminar.name
181+
).all()
182+
183+
account_ts_attendance_dict = {}
184+
185+
for row in account_ts_attendance_query:
186+
if not row[0] in account_ts_attendance_dict:
187+
account_ts_attendance_dict[row[0]] = []
188+
189+
account_ts_attendance_dict[row[0]].append(row[1])
190+
97191
# freshmen who have accounts
98192
for member in members:
99193
uid = member.uid
@@ -107,38 +201,31 @@ def get_fid_cm_count(member_id):
107201
if freshman_data.freshman_eval_result != "Pending" and internal:
108202
continue
109203

110-
h_meetings = [m.meeting_id for m in get_hm(member, only_absent=True)]
204+
member_missed_hms = []
205+
206+
if account_hm_missed.get(uid, 0) != 0:
207+
member_missed_hms = MemberHouseMeetingAttendance.query.join(
208+
HouseMeeting,
209+
MemberHouseMeetingAttendance.meeting_id == HouseMeeting.id
210+
).filter(
211+
HouseMeeting.date >= start_of_year(),
212+
MemberHouseMeetingAttendance.attendance_status == 'Absent',
213+
MemberHouseMeetingAttendance.uid == uid,
214+
).with_entities(
215+
func.array_agg(HouseMeeting.date)
216+
).scalar()
217+
218+
cms_attended = account_cm_count.get(uid, 0)
219+
111220
member_info = {
112221
'name': name,
113222
'uid': uid,
114223
'eval_date': freshman_data.eval_date.strftime("%Y-%m-%d"),
115224
'signatures_missed': freshman_data.signatures_missed,
116-
'committee_meetings': len(get_cm(member)),
117-
'committee_meetings_passed': len(get_cm(member)) >= 6,
118-
'house_meetings_missed':
119-
[
120-
{
121-
"date": m.date.strftime("%Y-%m-%d"),
122-
"reason":
123-
MemberHouseMeetingAttendance.query.filter(
124-
MemberHouseMeetingAttendance.uid == uid,
125-
MemberHouseMeetingAttendance.meeting_id == m.id).first().excuse
126-
}
127-
for m in HouseMeeting.query.filter(
128-
HouseMeeting.id.in_(h_meetings)
129-
)
130-
],
131-
'technical_seminars':
132-
[seminar.name for seminar in TechnicalSeminar.query.join(
133-
MemberSeminarAttendance,
134-
MemberSeminarAttendance.seminar_id == TechnicalSeminar.id
135-
).with_entities(
136-
TechnicalSeminar.name
137-
).filter(
138-
TechnicalSeminar.timestamp > start_of_year(),
139-
MemberSeminarAttendance.uid == member.uid,
140-
TechnicalSeminar.approved == True # pylint: disable=singleton-comparison
141-
).all()],
225+
'committee_meetings': cms_attended,
226+
'committee_meetings_passed': cms_attended >= 6,
227+
'house_meetings_missed': member_missed_hms,
228+
'technical_seminars': account_ts_attendance_dict.get(uid, []),
142229
'social_events': freshman_data.social_events,
143230
'comments': freshman_data.other_notes,
144231
'ldap_account': True,

0 commit comments

Comments
 (0)