perf: replace blocking requests.get with aiohttp in get_player_headshot (#100) #166
No reviewers
Labels
No Label
ai-changes-requested
ai-failed
ai-pr-opened
ai-reviewed
ai-reviewing
ai-working
autonomous
bug
enhancement
feature
in-queue
performance
security
size:M
size:S
tech-debt
tests
todo
type:feature
type:stability
No Milestone
No project
No Assignees
3 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: cal/paper-dynasty-discord#166
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "issue/100-perf-replace-blocking-requests-get-with-aiohttp-in"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #100
Summary
Replaced the synchronous
requests.get()call inget_player_headshot()with an asyncaiohttp.ClientSessionrequest, matching the pattern already used in the adjacentget_player_photo()function in the same file.Changes
helpers/main.py:get_player_headshot()— replacedrequests.get(req_url, timeout=2).textwithaiohttp.ClientSessionasync context manager usingaiohttp.ClientTimeout(total=2). Timeout value preserved (2s).aiohttpwas already imported at the top of the file.Before
After
Impact
Event loop no longer blocks on headshot cache misses. The bare
except: passfallback is preserved — any network error still falls through toget_player_photo().Test Results
No test suite for this function. Ruff lint passed on commit.
AI Code Review
Files Reviewed
helpers/main.py(modified)Findings
Correctness
No issues found.
textis assigned inside theasync withblocks and consumed outside them — correct. Python has no block scoping sotextis accessible after the context managers exit normally. If aiohttp raises beforetextis assigned, the exception propagates toexcept: passand we never reachsoup = BeautifulSoup(text, ...).soupis placed outside the innerasync withblocks — response connection is released before BeautifulSoup parses the body. Correct aiohttp usage:resp.text()reads the full body eagerly, so parsing safely happens after the context managers close.aiohttp.ClientTimeout(total=2)matches the originaltimeout=2semantics (total wall-clock timeout).aiohttpconfirmed imported at line 8.requestsis not directly imported inhelpers/main.py(arrives via star import fromrandom_content); removing the only direct usage here is safe.except: passfallback toget_player_photo()preserved unchanged.get_player_photo()function exactly.Security
No issues found.
Style & Conventions
Matches existing
get_player_photo()pattern in the same file.Suggestions
None.
Verdict: APPROVED
Clean async conversion. Correct context manager usage, error handling preserved, pattern-consistent with adjacent function. No correctness, security, or convention issues. (Posted as COMMENT — Gitea blocks self-approval.)
Automated review by Claude PR Reviewer
AI Code Review
Files Reviewed
helpers/main.py(modified —get_player_headshot()only)Findings
Correctness
No issues found.
textis assigned inside the innermost context manager.soup = BeautifulSoup(text, "html.parser")is correctly placed outside theasync withblocks but still inside thetry:—textis a fully-populated string at that point. NoUnboundLocalErrorrisk.requests.get(timeout=2)andaiohttp.ClientTimeout(total=2)are both total-timeout-2s.except: passunchanged —asyncio.TimeoutErrorandaiohttp.ClientErrorare both caught and fall through toget_player_photo().return await get_player_photo(player)fallback is outside the try/except (unchanged), so it still fires on both exception and no-headshot-found paths.aiohttpalready imported at line 8. No new imports needed.requestsis not directly imported inhelpers/main.py(comes in transitively viafrom api_calls import *). The removal of the onlyrequests.get()call leaves no dead direct import in this file.Security
No issues found. URL is constructed from DB-sourced
bbref_id/p_name— not user-supplied input. No change in attack surface.Style & Conventions
Pattern matches
get_player_photo()in the same file exactly (doubleasync with aiohttp.ClientSession()). Clean.Suggestions
get_player_headshot()— acknowledged in PR. A smoke-test mockingaiohttp.ClientSessionwould guard against future regressions, but not a blocker.Verdict: APPROVED
Functionally equivalent replacement. Async pattern is correct, timeout preserved, error handling unchanged. No correctness or security issues.
Automated review by Claude PR Reviewer
d957bbe7abto25551130e9