perf: parallelize scout opportunity creation and remove sleep(2) (#101) #156
No reviewers
Labels
No Label
ai-changes-requested
ai-failed
ai-pr-opened
ai-reviewed
ai-reviewing
ai-working
ai-working
bug
enhancement
feature
in-queue
performance
security
tech-debt
todo
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: cal/paper-dynasty-discord#156
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "issue/101-perf-parallelize-scout-opportunity-creation-and-re"
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 #101
Summary
Replace the sequential
forloop +asyncio.sleep(2)inopen_st_pr_packs()with a singleasyncio.gather()call that creates all scout opportunities concurrently.Before: Each pack's scout opportunity was created one at a time with a 2-second sleep between each — adding ~8 seconds of post-display delay for a 5-pack open.
After: All scout opportunities are created simultaneously. Zero artificial delay.
Changes
helpers/main.py: Replace sequential loop andasyncio.sleep(2)withasyncio.gather()over all pack IDs. Theif pack_cards:guard is removed —create_scout_opportunity()already has an earlyif not pack_cards: returnguard internally.Why the sleep was there
The sleep was a blunt rate-limiting workaround for sequential Discord channel sends. With parallel execution, discord.py's built-in rate-limit handling is sufficient — it retries with backoff automatically if the API returns 429.
Other observations
pack_cardswas empty (sleep was outside theif pack_cards:block) — minor inefficiency in the original, now moot.AI Code Review
Files Reviewed
helpers/main.py(modified — lines 1788–1796)Findings
Correctness
if pack_cards:guard removal is safe.create_scout_opportunity()has its ownif not pack_cards: returnguard athelpers/scouting.py:197. The outer guard is redundant and its removal is correct.asyncio.sleep(2)removal is correct. The original sleep fired even whenpack_cardswas empty (it was outside theif pack_cards:block), making it unconditional per-pack delay. Removing it is sound — discord.py's rate-limit handler retries with backoff on 429 responses without requiring manual sleeps.asyncio.gather()usage is correct. All shared arguments (team,pack_channel,author,context) are read-only withincreate_scout_opportunity(). The return value (list ofNone) is discarded.asyncio.gather(*[])with an emptypack_idslist returns[]safely.db_postandchannel.sendcalls insidecreate_scout_opportunity()are wrapped in their own try/except blocks, so individual failures degrade gracefully without affecting sibling coroutines.Security
Style & Conventions
asyncio.gather()pattern established in PR #157 (display_cards). Consistent.Suggestions
Verdict: COMMENT
Functionally correct. The
if pack_cards:guard removal is safe due to the internal early-return increate_scout_opportunity(). The sleep removal is justified and the parallelisation matches the existingasyncio.gather()pattern in this codebase. Gitea blocks self-approval — posting as COMMENT.Automated review by Claude PR Reviewer
Approved via pd-pr