Skip to content

fix!: do not count downtime towards crawler_runtime after migration or resurrection - #2204

Draft
Pijukatel wants to merge 1 commit into
v2from
claude/actor-resurrection-time-tracking-bixxkl
Draft

Pijukatel wants to merge 1 commit into
v2from
claude/actor-resurrection-time-tracking-bixxkl

Conversation

@Pijukatel

@Pijukatel Pijukatel commented Aug 31, 2026 •

Copy link
Copy Markdown
Collaborator

Description

After an Actor migration, resurrection or abort, crawler_runtime misbehaved: the first periodic log of the resumed run included the whole downtime (e.g. 38.01s right after resurrection of a run whose real runtime was ~0.5 s), the downtime could get permanently baked into the statistics, and with repeated resurrections only the last run's segment survived.

This is a v2-targeted rework that makes the runtime a plain accumulated statistic:

  • StatisticsState.accumulated_runtime (persisted as crawlerRuntimeMillis) holds the runtime accumulated by the previous runs; the read-only crawler_runtime property adds the elapsed time of the run in progress, measured by the crawler_last_started_at/crawler_finished_at timestamps.
  • The field serializer for accumulated_runtime writes the live total, so every persist is an exact checkpoint: a state persisted mid-run (periodic persist, migration event) carries the runtime up to that moment. After an unclean termination, the resumed run continues from the last checkpoint, so no downtime is ever counted and at most the tail since the last persist is lost.
  • Statistics.__aenter__ clears the previous run's timestamps before the periodic logger starts, so the restored total is reported as-is and the downtime between runs can never leak into the runtime. The documented invariant: timestamps of a loaded state are history, not measurement anchors.
  • A backwards wall clock jump during a run cannot push the runtime below the accumulated total (the live segment is clamped at zero).
  • No new public API beyond the documented accumulated_runtime field: Statistics communicates with the state only through the existing public timestamp fields.

Guarantees (all covered by tests in tests/unit/_statistics/test_persistence.py):

  1. A fresh run's first periodic statistics log reports a runtime of exactly 0.
  2. A resumed run's first periodic log reports exactly the previously persisted runtime.
  3. The runtime accumulates correctly over any number of persist/resume cycles.
  4. Aborts/migrations (unclean termination, no final persist) resume from the last periodic checkpoint, excluding downtime.

Breaking changes (v2)

  • StatisticsState.crawler_runtime_for_serialization is removed; crawler_runtime is a read-only property (the setter was already removed by refactor!: remove deprecated StatisticsState.crawler_runtime setter #2315) backed by the new accumulated_runtime field.
  • crawlerRuntimeMillis is serialized as a number of milliseconds, consistent with the other *Millis fields and with Crawlee for JavaScript, instead of an ISO 8601 duration string. (A v1 state with an ISO duration string still loads, since the timedelta_ms validator falls back to ISO parsing, but v1 compatibility is not a goal of this PR.)
  • The unused StatisticsState fields errors, retry_errors, requests_finished_per_minute and requests_failed_per_minute are removed. They were never populated; the FinalStatistics fields of the same names are unaffected.

The upgrading guide (docs/upgrading/upgrading_to_v2.md) documents all of the above.

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_01VMHwDx87jV4rnu5LkbpNxy

@github-actions github-actions Bot added this to the 148th sprint - Tooling team milestone Aug 31, 2026
@github-actions github-actions Bot added t-tooling Issues with this label are in the ownership of the tooling team. tested Temporary label used only programatically for some analytics. labels Aug 31, 2026
@codecov

codecov Bot commented Aug 31, 2026 •

Copy link
Copy Markdown

Codecov Report

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

Additional details and impacted files
@@          Coverage Diff          @@
##             v2    #2204   +/-   ##
=====================================
  Coverage      ?   94.03%           
=====================================
  Files         ?      184           
  Lines         ?    13568           
  Branches      ?        0           
=====================================
  Hits          ?    12759           
  Misses        ?      809           
  Partials      ?        0           
Flag Coverage Δ
unit 94.03% <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.

@Pijukatel

Copy link
Copy Markdown
Collaborator Author

Waiting for V2 as this might be breaking change and will inlcude removal of deprecated fields

@Pijukatel Pijukatel changed the title fix: do not count downtime towards crawler_runtime after migration or resurrection fix!: do not count downtime towards crawler_runtime after migration or resurrection Sep 3, 2026
@Pijukatel
Pijukatel force-pushed the claude/actor-resurrection-time-tracking-bixxkl branch from 4b9f3e5 to 8af9ee3 Compare October 20, 2026 07:47
@Pijukatel
Pijukatel changed the base branch from master to v2 October 20, 2026 07:48
@Pijukatel
Pijukatel force-pushed the claude/actor-resurrection-time-tracking-bixxkl branch 2 times, most recently from d6cf367 to 278c17b Compare October 20, 2026 09:43
…r resurrection

The `crawler_runtime` statistic no longer counts the downtime between
the runs of a resumed crawler, and it accumulates correctly across any
number of persist/resume cycles:

- The first periodic statistics log reports exactly the runtime
  accumulated so far: zero for a fresh start, the previously persisted
  total for a resumed run.
- The accumulated runtime is stored in the new `accumulated_runtime`
  field, persisted under `crawlerRuntimeMillis`. Every persist writes
  the live total, so a state persisted mid-run (migration, abort)
  carries the runtime up to that moment and a resumed run continues
  from the last checkpoint.
- The timestamps of the previous run are cleared before the new run
  starts being measured, so they cannot leak the downtime into the
  runtime, and a backwards clock jump during a run cannot push the
  runtime below the accumulated total.

BREAKING CHANGE: `StatisticsState.crawler_runtime_for_serialization`
is removed; the `crawler_runtime` property is backed by the new
`accumulated_runtime` field. `crawlerRuntimeMillis` is serialized as
a number of milliseconds instead of an ISO 8601 duration string. The
unused state fields `errors`, `retry_errors`,
`requests_finished_per_minute` and `requests_failed_per_minute` are
removed from `StatisticsState`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VMHwDx87jV4rnu5LkbpNxy
@Pijukatel
Pijukatel force-pushed the claude/actor-resurrection-time-tracking-bixxkl branch from 278c17b to d4efa71 Compare October 20, 2026 11:26

This branch has not been deployed

No deployments
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. tested Temporary label used only programatically for some analytics.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove deprecated StatisticsState.crawler_runtime setter

3 participants