Skip to content

fix(throttling-manager): Open the per-domain sub-queues on first use instead of on insert - #2177

Open
Mantisus wants to merge 5 commits into
apify:masterfrom
Mantisus:throttling-sub-opener
Open

fix(throttling-manager): Open the per-domain sub-queues on first use instead of on insert#2177
Mantisus wants to merge 5 commits into
apify:masterfrom
Mantisus:throttling-sub-opener

Conversation

@Mantisus

Copy link
Copy Markdown
Collaborator

Description

  • A sub-manager for every configured domain is now opened on first use, instead of only when a request for that domain is added. The read paths used to iterate an empty dict on a fresh process, so requests a previous run left in a throttled-<domain> queue were invisible: the crawl reported itself finished, and purge() and drop() could not clear them either. Resuming those requests needs purge_on_start=False; with the default the queues are now purged at start instead of being left orphaned on disk.

Issues

@Mantisus Mantisus self-assigned this Aug 19, 2026
@vdusek
vdusek requested review from apify-factory and a balanced review from Copilot August 20, 2026 07:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes throttled request persistence across restarts by lazily opening all configured per-domain queues on first storage operation.

Changes:

  • Adds synchronized sub-manager initialization across read/write paths.
  • Tracks requests fetched from the inner queue for correct completion routing.
  • Adds restart, purge, drop, routing, and concurrency tests.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/crawlee/request_loaders/_throttling_request_manager.py Reopens configured sub-queues and tracks request ownership.
tests/unit/test_throttling_request_manager.py Tests persistence and updated lifecycle behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +437 to +439
if request.unique_key in self._in_flight_from_inner:
self._in_flight_from_inner.discard(request.unique_key)
return self._inner
async with self._sub_managers_lock:
if self._sub_managers_ready:
return
await asyncio.gather(*(self._open_sub_manager(domain) for domain in self._domain_states))
Comment on lines +49 to +50
The class is generic over the wrapped manager type. On the first call to any of its methods, the
`request_manager_opener` callback opens one sub-manager per configured domain, so every sub-manager shares the same
self._sub_managers: dict[str, TRequestManager] = {}
self._sub_managers_ready = False
self._sub_managers_lock = asyncio.Lock()
self._in_flight_from_inner: set[str] = set()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ThrottlingRequestManager never reopens its sub-queues, so a restart strands throttled requests

4 participants