Skip to content

refactor: use asyncio.TaskGroup in the error snapshotter - #2321

Merged
vdusek merged 7 commits into
v2from
task-group
Oct 14, 2026
Merged

vdusek merged 7 commits into
v2from
task-group

Conversation

@vdusek

@vdusek vdusek commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Converts the error snapshotter's concurrent HTML and screenshot saves to asyncio.TaskGroup. Its caller catches and logs any Exception, so the ExceptionGroup doesn't change behavior.

The other places from the issue keep their current code:

  • TaskGroup wraps failures in an ExceptionGroup, which defeats the crawler's type-based error handling (retries, error statistics) and users' except clauses. That rules out the robots.txt skips, BrowserPool.new_page_with_each_plugin and infinite_scroll, where the gain is small.
  • ThrottlingRequestManager reads are side-effect-free, so a task group adds code without changing anything. drop, purge and the sub-manager opening must let every call finish.
  • LocalEventManager runs its readings in to_thread, which cancellation can't stop.
  • The autoscaled pool would start cancelling healthy workers when one fails.
  • The event manager, RQ background batches, RecurringTask and the sitemap loader own tasks that outlive the call that starts them. _merge_async_generators is an async generator.

Closes: #1722

✍️ Drafted by Claude Code

@vdusek vdusek added the t-tooling Issues with this label are in the ownership of the tooling team. label Oct 13, 2026
@vdusek vdusek self-assigned this Oct 13, 2026
@codecov

codecov Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (v2@f3483e5). Learn more about missing BASE report.

Additional details and impacted files
@@          Coverage Diff          @@
##             v2    #2321   +/-   ##
=====================================
  Coverage      ?   94.13%           
=====================================
  Files         ?      183           
  Lines         ?    13569           
  Branches      ?        0           
=====================================
  Hits          ?    12773           
  Misses        ?      796           
  Partials      ?        0           
Flag Coverage Δ
unit 94.13% <100.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…d infinite_scroll

BREAKING CHANGE: failures from these calls are raised wrapped in an `ExceptionGroup`:
- `BasicCrawler.add_requests` and `enqueue_links` / `extract_links` when the `on_skipped_request` callback raises for a robots.txt-disallowed request
- `BrowserPool.new_page_with_each_plugin`
- `infinite_scroll` (`PlaywrightCrawlingContext.infinite_scroll`)
@vdusek vdusek changed the title refactor: use task groups for concurrent fan-out refactor!: use asyncio.TaskGroup for concurrent fan-out Oct 14, 2026
@vdusek vdusek changed the title refactor!: use asyncio.TaskGroup for concurrent fan-out refactor: use asyncio.TaskGroup in the error snapshotter Oct 14, 2026
@vdusek
vdusek requested review from Mantisus and Pijukatel October 14, 2026 13:17
@vdusek
vdusek marked this pull request as ready for review October 14, 2026 13:17

@apify-approval-mirror apify-approval-mirror Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Mirroring approval from @Mantisus.

@vdusek
vdusek merged commit 792e5a6 into v2 Oct 14, 2026
30 checks passed
@vdusek
vdusek deleted the task-group branch October 14, 2026 13:41
@vdusek vdusek linked an issue Oct 14, 2026 that may be closed by this pull request
vdusek added a commit that referenced this pull request Oct 16, 2026
Converts the error snapshotter's concurrent HTML and screenshot saves to
`asyncio.TaskGroup`. Its caller catches and logs any `Exception`, so the
`ExceptionGroup` doesn't change behavior.

The other places from the issue keep their current code:

- `TaskGroup` wraps failures in an `ExceptionGroup`, which defeats the
crawler's type-based error handling (retries, error statistics) and
users' `except` clauses. That rules out the robots.txt skips,
`BrowserPool.new_page_with_each_plugin` and `infinite_scroll`, where the
gain is small.
- `ThrottlingRequestManager` reads are side-effect-free, so a task group
adds code without changing anything. `drop`, `purge` and the sub-manager
opening must let every call finish.
- `LocalEventManager` runs its readings in `to_thread`, which
cancellation can't stop.
- The autoscaled pool would start cancelling healthy workers when one
fails.
- The event manager, RQ background batches, `RecurringTask` and the
sitemap loader own tasks that outlive the call that starts them.
`_merge_async_generators` is an async generator.

Closes: #1722

*✍️ Drafted by Claude Code*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

t-tooling Issues with this label are in the ownership of the tooling team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Adopt asyncio.TaskGroup for structured concurrency

3 participants