Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions frontend/src/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,13 @@ export default function App() {
);

useEffect(() => {
fetchProfile();
fetchRequirements();
}, [fetchProfile, fetchRequirements]);
fetchProfile();
if (window.__TIGERPATH_PRELOADED_REQUIREMENTS__) {
handleRequirementData(window.__TIGERPATH_PRELOADED_REQUIREMENTS__);
Comment on lines +74 to +75
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fetch requirements when preload payload is empty

This condition treats an empty preloaded payload as success, so the API fallback never runs. In this commit the server can serialize [] for cases like unsupported majors or preload exceptions, and because [] is truthy in JavaScript, users can end up stuck with an empty requirements pane instead of the normal /api/v1/get_requirements/ result (which includes unsupported-major messaging and degree progress).

Useful? React with 👍 / 👎.

} else {
fetchRequirements();
}
}, [fetchProfile, fetchRequirements, handleRequirementData]);

const prevScheduleRef = React.useRef(null);
useEffect(() => {
Expand Down
26 changes: 8 additions & 18 deletions tigerpath/majors_and_certificates/scripts/verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,15 @@

# Allow overriding the data repo base via env var for easy testing
# Must end with a trailing slash and point to a raw.githubusercontent.com base
REMOTE_DATA_REPO_URL = os.getenv(
"DEPT_DATA_URL",
"https://raw.githubusercontent.com/TigerAppsOrg/Princeton-Departmental-Data/old/",
)

# connect/read timeouts so requests never hang workers indefinitely
_HTTP_TIMEOUT = (3.05, 7)
import pathlib

_LOCAL_DATA_DIR = pathlib.Path(__file__).resolve().parent.parent.parent / "requirements_data"

@lru_cache(maxsize=256)
def _fetch_remote_yaml(path: str):
"""
Fetch and parse YAML from the remote requirements repository with a timeout.

Results are cached in-process to avoid repeated network requests on hot paths.
"""
resp = requests.get(REMOTE_DATA_REPO_URL + path, timeout=_HTTP_TIMEOUT)
resp.raise_for_status()
return yaml.safe_load(resp.text)
def _load_yaml(path: str):
"""Load and parse YAML from the local requirements data directory."""
filepath = _LOCAL_DATA_DIR / path
return yaml.safe_load(filepath.read_text())


MAJORS_LOCATION = "majors/" # relative path to folder containing the major requirements JSONs
Expand Down Expand Up @@ -149,7 +139,7 @@ def check_requirements(req_file, courses, year):
:returns: A simplified json with info about how much of each requirement is satisfied
:rtype: (bool, dict, dict)
"""
req = _fetch_remote_yaml(req_file)
req = _load_yaml(req_file)
courses = _init_courses(courses, req, year)
req = _init_req(req, year)
_mark_possible_reqs(req, courses)
Expand Down Expand Up @@ -205,7 +195,7 @@ def get_courses_by_path(path):
req_filepath = os.path.join(DEGREES_LOCATION, filename)
else:
raise ValueError("Path malformatted.")
req = _fetch_remote_yaml(req_filepath)
req = _load_yaml(req_filepath)
_init_year_switch(req, year)
subreq = _get_req_by_path(req, path, year)
if not subreq:
Expand Down
Loading
Loading