You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Replace is_empty/is_finished with check_readiness() and add pacing signals to RequestManager #2296
BasicCrawler asks the request manager for work through is_empty() / is_finished(), and it finds a ThrottlingRequestManager with isinstance checks in six places (_basic_crawler.py lines 720, 741, 1457, 1651, 1733, 1802). Any wrapper hides the throttler, which is the root cause of #2238. A manager also has no way to report "requests exist, but none is ready until T" other than the throttler-specific get_stall_reason().
JS v4 replaced the two booleans and the capability probe with members of the request manager interface. Port the same shape.
Proposed solution
check_readiness() on RequestLoader and RequestManager replaces is_empty() and is_finished(). It returns one of ready, waiting (with an optional ready_at), stalled (with a reason, managers only) or finished. RequestManagerTandem combines its two sources with the precedence ready > stalled > waiting > finished.
record_pacing_signal(signal) -> bool on RequestManager. The crawler reports 429/503 responses (with Retry-After), robots.txt crawl-delay and a same-domain delay floor as signals. Wrappers such as RequestManagerTandem forward signals without looking inside them. The return value tells the crawler whether anything consumed the signal, which replaces the "not using ThrottlingRequestManager" warnings.
get_pending_count() on RequestLoader. RequestManagerTandem.get_total_count() uses it; today it adds the loader total to the manager total, so every transferred request is counted twice.
The inner argument of ThrottlingRequestManager becomes optional and defaults to the default request queue.
Storage backends are not affected: RequestQueueClient keeps is_empty() / is_finished() (#1985), as in JS.
Acceptance criteria
No isinstance(..., ThrottlingRequestManager) left in the crawlers.
A throttler behind RequestManagerTandem applies 429 backoff and crawl-delay.
RequestManagerTandem.get_total_count() counts each request once.
Upgrade notes for custom RequestLoader / RequestManager implementations.
Activity
janbuchar commentedon Oct 15, 2026
You should probably also add
set_expected_request_processing_timehttps://github.com/apify/crawlee/blob/redelete-mayberunintervalsecs/packages/core/src/storages/request-manager.ts