Skip to content

Commit 339c462

Browse files
gracech1Copilot
andcommitted
load_next_menu now only asks for one auth token
Co-authored-by: Copilot <copilot@github.com>
1 parent 237fbf7 commit 339c462

2 files changed

Lines changed: 22 additions & 18 deletions

File tree

backend/dining/api_wrapper.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import datetime
22
import json
33
import logging
4+
import threading
45
from concurrent.futures import ThreadPoolExecutor, as_completed
56

67
import requests
@@ -50,24 +51,28 @@
5051
class DiningAPIWrapper:
5152
def __init__(self):
5253
self.token = None
54+
self.token_lock = threading.Lock() # Only one thread should update the token at a time
5355
self.expiration = timezone.localtime()
5456
self.openid_endpoint = (
5557
"https://sso.apps.k8s.upenn.edu/auth/realms/master/protocol/openid-connect/token"
5658
)
5759

5860
def update_token(self):
59-
if self.expiration > timezone.localtime():
60-
return
61-
body = {
62-
"client_id": settings.DINING_ID,
63-
"client_secret": settings.DINING_SECRET,
64-
"grant_type": "client_credentials",
65-
}
66-
response = requests.post(self.openid_endpoint, data=body).json()
67-
if "error" in response:
68-
raise APIError(f"Dining: {response['error']}, {response.get('error_description')}")
69-
self.expiration = timezone.localtime() + datetime.timedelta(seconds=response["expires_in"])
70-
self.token = response["access_token"]
61+
with self.token_lock:
62+
if self.expiration > timezone.localtime():
63+
return
64+
body = {
65+
"client_id": settings.DINING_ID,
66+
"client_secret": settings.DINING_SECRET,
67+
"grant_type": "client_credentials",
68+
}
69+
response = requests.post(self.openid_endpoint, data=body).json()
70+
if "error" in response:
71+
raise APIError(f"Dining: {response['error']}, {response.get('error_description')}")
72+
self.expiration = timezone.localtime() + datetime.timedelta(
73+
seconds=response["expires_in"]
74+
)
75+
self.token = response["access_token"]
7176

7277
def request(self, *args, **kwargs):
7378
"""Make a signed request to the dining API."""
@@ -143,9 +148,8 @@ def fetch_menu(self, venue_id, date):
143148
"""
144149
Calls API to fetch menu for a given venue and date
145150
"""
146-
worker = DiningAPIWrapper() # avoid shared mutable token state across threads
147151
menu_base = OPEN_DATA_ENDPOINTS["MENUS"]
148-
response = worker.request("GET", f"{menu_base}?cafe={venue_id}&date={date}")
152+
response = self.request("GET", f"{menu_base}?cafe={venue_id}&date={date}")
149153
if response.status_code != 200:
150154
raise APIError("Dining: error connecting to API " + response.text)
151155
return (

backend/dining/management/commands/load_next_menu.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,13 @@ class Command(BaseCommand):
1414
the next 7 days, including the original date.
1515
"""
1616

17-
def load_one_menu(self, today, delta, *args, **kwargs):
17+
def load_one_menu(self, today, wrapper, delta, *args, **kwargs):
1818
"""
1919
Loads menu for a single day
2020
"""
2121
date_to_load = today + datetime.timedelta(days=delta)
2222

23-
d = DiningAPIWrapper()
24-
d.load_menus(date_to_load)
23+
wrapper.load_menus(date_to_load)
2524
delete_menu_view_cache(date_to_load)
2625

2726
# Error logging
@@ -32,6 +31,7 @@ def handle(self, *args, **kwargs):
3231
Load menu for the next 7 days
3332
"""
3433
today = timezone.now().date()
34+
d = DiningAPIWrapper()
3535

3636
for i in range(7):
37-
self.load_one_menu(today, i)
37+
self.load_one_menu(today, d, i)

0 commit comments

Comments
 (0)