Repository navigation
refactor: Reset per-run crawler state on every run() call
#2377
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
Mantisus
wants to merge
3
commits into
apify:v2
Choose a base branch
from
Mantisus:crawler-run
base: v2
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.
Open
Changes from all commits
Commits
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
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,82 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from typing import TYPE_CHECKING, Generic | ||
|
|
||
| from typing_extensions import TypeVar | ||
|
|
||
| from crawlee._utils.log import LoggerOnce | ||
| from crawlee.autoscaling import AutoscaledPool | ||
| from crawlee.statistics import StatisticsState | ||
|
|
||
| if TYPE_CHECKING: | ||
| import logging | ||
| from collections.abc import Awaitable, Callable | ||
|
|
||
| from crawlee.autoscaling import ConcurrencyConsumer | ||
| from crawlee.autoscaling._types import ConcurrencySystemInterface | ||
|
|
||
| TStatisticsState = TypeVar('TStatisticsState', bound=StatisticsState, default=StatisticsState) | ||
|
|
||
|
|
||
| class CrawlerRun(Generic[TStatisticsState]): | ||
| """Everything that belongs to a single `BasicCrawler.run` call. | ||
|
|
||
| The crawler builds a fresh instance for every run, so nothing has to be reset between runs. A finished run stays | ||
| readable as the history of the last crawl, so liveness is asked about explicitly with `is_live`. | ||
| """ | ||
|
|
||
| def __init__( | ||
| self, | ||
| *, | ||
| logger: logging.Logger, | ||
| concurrency_system: ConcurrencySystemInterface, | ||
| consumer: ConcurrencyConsumer, | ||
| run_task_function: Callable[[str], Awaitable], | ||
| is_task_ready_function: Callable[[], Awaitable[bool]], | ||
| is_finished_function: Callable[[], Awaitable[bool]], | ||
| ) -> None: | ||
| self._autoscaled_pool = AutoscaledPool( | ||
| concurrency_system=concurrency_system, | ||
| consumer=consumer, | ||
| run_task_function=run_task_function, | ||
| is_task_ready_function=is_task_ready_function, | ||
| is_finished_function=is_finished_function, | ||
| ) | ||
| self._logger_once = LoggerOnce(logger) | ||
| self._stop_requested = False | ||
| self._finished = False | ||
|
|
||
| self.failed = False | ||
| """Whether a request has failed while the crawler aborts on an error.""" | ||
|
|
||
| self.handled_request = False | ||
| """Whether this run has marked any request as handled.""" | ||
|
|
||
| self.previous_state: TStatisticsState | None = None | ||
| """The statistics state at the last status update of this run.""" | ||
|
|
||
| @property | ||
| def is_live(self) -> bool: | ||
| """Whether the `BasicCrawler.run` call this belongs to is still executing.""" | ||
| return not self._finished | ||
|
|
||
| @property | ||
| def stop_requested(self) -> bool: | ||
| """Whether a graceful shutdown of this run has been requested.""" | ||
| return self._stop_requested | ||
|
|
||
| async def dispatch_requests(self) -> None: | ||
| """Run the task loop until the crawl is over. The concurrency system has to be active by now.""" | ||
| await self._autoscaled_pool.run() | ||
|
|
||
| def stop(self) -> None: | ||
| """Ask the run to stop taking new requests.""" | ||
| self._stop_requested = True | ||
|
|
||
| def log_once(self, message: str, key: str) -> None: | ||
| """Log `message` the first time this run asks for it under `key`.""" | ||
| self._logger_once.log(message, key=key) | ||
|
|
||
| def finish(self) -> None: | ||
| """Mark the run as history, so that the crawler can start another one.""" | ||
| self._finished = True |
Oops, something went wrong.
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.