-
Notifications
You must be signed in to change notification settings - Fork 173
Enhance _info method to check file and directory info in parallel #786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
yuxin00j
wants to merge
15
commits into
fsspec:main
Choose a base branch
from
ankitaluthra1:optimize-info
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+232
−9
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
f10f7e4
Enhance _info method to check file and directory info in parallel.
yuxin00j 207a48d
perf: Add latency logging for `_get_object` and `_get_directory_info`…
yuxin00j 8b266d4
Improve test coverage for parallel _info
yuxin00j b386d12
Optimize _info with early return using asyncio.wait
yuxin00j 15cba92
Refactor tasks dictionary to set in _info method per review feedback …
yuxin00j cb0888e
Update gcsfs/core.py
yuxin00j a9958af
Implement try...finally block in _info for robust task cleanup per re…
yuxin00j f6c7e55
Refactor _info to use parallel_tasks_first_completed and fix logic bugs
yuxin00j c55871c
Move `parallel_tasks_first_completed` import to top level in core.py
yuxin00j e452199
Add test_info_parallel_dir_first to cover directory listing finishes …
yuxin00j 63f9150
Fix info regression and directory marker check
yuxin00j ed04bf2
Address review comments: ensure Python 3.11 compatibility in asyncio.…
yuxin00j 2f40661
Address review comments for PR #786
yuxin00j d40141f
Rename exact_res to get_object_res for consistency
yuxin00j df864d8
Fix lint issues: black and end-of-file-fixer
yuxin00j File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| import asyncio | ||
| from contextlib import asynccontextmanager | ||
|
|
||
|
|
||
| @asynccontextmanager | ||
| async def parallel_tasks_first_completed(coros): | ||
| """ | ||
| Starts coroutines in parallel and enters the context as soon as | ||
| at least one task has completed. Automatically cancels pending tasks | ||
| when exiting the context. | ||
| """ | ||
| tasks = [asyncio.create_task(c) for c in coros] | ||
| try: | ||
| # Suspend until the first task finishes for maximum responsiveness | ||
| done, pending = await asyncio.wait( | ||
| set(tasks), return_when=asyncio.FIRST_COMPLETED | ||
| ) | ||
| yield tasks, done, pending | ||
| finally: | ||
| # Ensure 'losing' tasks are cancelled immediately | ||
| for t in tasks: | ||
| if not t.done(): | ||
| t.cancel() |
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| import asyncio | ||
|
|
||
| import pytest | ||
|
|
||
| from gcsfs.concurrency import parallel_tasks_first_completed | ||
|
|
||
|
|
||
| @pytest.mark.asyncio | ||
| async def test_parallel_tasks_first_completed_basic(): | ||
| async def slow_task(): | ||
| await asyncio.sleep(1) | ||
| return "slow" | ||
|
|
||
| async def fast_task(): | ||
| await asyncio.sleep(0.1) | ||
| return "fast" | ||
|
|
||
| async with parallel_tasks_first_completed([slow_task(), fast_task()]) as ( | ||
| tasks, | ||
| done, | ||
| pending, | ||
| ): | ||
| assert len(done) == 1 | ||
| assert len(pending) == 1 | ||
| completed_task = done.pop() | ||
| assert completed_task.result() == "fast" | ||
| assert len(tasks) == 2 | ||
|
|
||
|
|
||
| @pytest.mark.asyncio | ||
| async def test_parallel_tasks_first_completed_cancellation(): | ||
| task_cancelled = False | ||
|
|
||
| async def slow_task(): | ||
| nonlocal task_cancelled | ||
| try: | ||
| await asyncio.sleep(1) | ||
| except asyncio.CancelledError: | ||
| task_cancelled = True | ||
| raise | ||
|
|
||
| async def fast_task(): | ||
| await asyncio.sleep(0.1) | ||
| return "fast" | ||
|
|
||
| async with parallel_tasks_first_completed([slow_task(), fast_task()]) as ( | ||
| tasks, | ||
| done, | ||
| pending, | ||
| ): | ||
| assert len(done) == 1 | ||
| completed_task = done.pop() | ||
| assert completed_task.result() == "fast" | ||
|
|
||
| # After exiting context, slow_task should be cancelled | ||
| await asyncio.sleep(0.1) # Give it a moment to run cancellation cleanup | ||
| assert task_cancelled | ||
|
|
||
|
|
||
| @pytest.mark.asyncio | ||
| async def test_parallel_tasks_first_completed_exception(): | ||
| async def error_task(): | ||
| await asyncio.sleep(0.1) | ||
| raise ValueError("error") | ||
|
|
||
| async def slow_task(): | ||
| await asyncio.sleep(1) | ||
| return "slow" | ||
|
|
||
| async with parallel_tasks_first_completed([error_task(), slow_task()]) as ( | ||
| tasks, | ||
| done, | ||
| pending, | ||
| ): | ||
| assert len(done) == 1 | ||
| completed_task = done.pop() | ||
| with pytest.raises(ValueError, match="error"): | ||
| completed_task.result() |
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
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.