fix: wrap blocking MirrorClient calls with asyncio.to_thread to prevent event loop starvation - #945
Merged
anderdc merged 5 commits intoMay 7, 2026
Conversation
…nt event loop starvation
Tet-9
force-pushed
the
fix/876-wrap-mirror-client-blocking-calls-asyncio-to-thread
branch
from
May 3, 2026 14:21
e7fd415 to
49f18c0
Compare
anderdc
requested changes
May 6, 2026
anderdc
left a comment
Collaborator
There was a problem hiding this comment.
Move import asyncio from inside evaluate_miners_pull_requests to the top of gittensor/validator/oss_contributions/reward.py with the other module-level imports.
Contributor
Author
Done 🫡 |
anderdc
approved these changes
May 7, 2026
This was referenced May 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #876
Problem
MirrorClientuses the synchronousrequestslibrary for all HTTP calls. The validator's forward path (forward.py) isasync def, and all mirror scoring and issue discovery functions are reached from it. Every blockingrequests.get(...)call ties up the event loop for the full round-trip time — often hundreds of milliseconds per call, seconds under Cloudflare throttle or cold cache conditions.This starves:
bt.loggingflush callbacksThe validator's apparent latency to other subnet participants spikes during every mirror scoring round.
Root Cause
Three blocking call sites were running synchronous I/O directly in the async context:
mirror_scan.py—client.get_miner_issues()inrun_mirror_issue_discovery(async)mirror_scan.py—client.get_pr_files()in_resolve_solving_pr_score(called from async chain)scoring.py—client.get_pr_files()inscore_mirror_pr(called from async chain)reward.py—load_mirror_miner_prs+score_mirror_miner_prscalled synchronously insideevaluate_miners_pull_requests(async)Fix
gittensor/validator/issue_discovery/mirror_scan.py_resolve_solving_pr_scoreand_score_miner_mirror_issuesasync defclient.get_pr_files()withawait asyncio.to_thread(...)inside_resolve_solving_pr_scoreclient.get_miner_issues()withawait asyncio.to_thread(...)inrun_mirror_issue_discoveryawaitto all call sites of the newly async functionsimport asynciogittensor/validator/oss_contributions/mirror/scoring.pyscore_mirror_prandscore_mirror_miner_prsasync defclient.get_pr_files()withawait asyncio.to_thread(...)insidescore_mirror_prawaittoscore_mirror_prcall site inscore_mirror_miner_prsimport asynciogittensor/validator/oss_contributions/reward.pyload_mirror_miner_prsremains synchronous — wrapped withawait asyncio.to_thread(...)score_mirror_miner_prsis now async — called directly withawaitimport asyncioResult
All blocking mirror HTTP calls now run on the thread pool via
asyncio.to_thread, freeing the event loop during mirror I/O. No changes to scoring logic, multipliers, or data flow.Files Changed
gittensor/validator/issue_discovery/mirror_scan.pygittensor/validator/oss_contributions/mirror/scoring.pygittensor/validator/oss_contributions/reward.py