Skip to content

feat: randomized jitter between place visits (Bundle E) - #37

Merged
Liohtml merged 2 commits into
mainfrom
claude/bundle-e-place-jitter
Jun 16, 2026
Merged

feat: randomized jitter between place visits (Bundle E)#37
Liohtml merged 2 commits into
mainfrom
claude/bundle-e-place-jitter

Conversation

@Liohtml

@Liohtml Liohtml commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Overview

Bundle E — adds randomized jitter between place visits in the enrich path (#25).

Previously, with enrich = true, the scraper navigated to every place URL at a fixed place_panel_delay interval (default 1.5 s) — a deterministic cadence that bot-detection can flag. This adds ScraperConfig::place_panel_jitter (default 750 ms): before each place visit the loop sleeps place_panel_delay + rand(0..=jitter).

Details

  • No new dependency. Jitter is drawn from a std-only entropy source (sub-second wall-clock nanos) via a pure, unit-tested jitter_ms(seed, max_ms) helper. The issue suggested rand; a weak seed is sufficient here since this only de-regularises timing.
  • Duration::ZERO disables jitter (jitter_ms returns 0 when max_ms == 0).
  • Unit test jitter_within_bounds covers the inclusive 0..=max range and the zero case; config_defaults asserts the new default.

Test plan

  • cargo build
  • cargo test (9 passed — adds jitter_within_bounds)
  • cargo fmt --all -- --check
  • cargo clippy --all-targets -- -D warnings

Closes #25

https://claude.ai/code/session_01TPpTHPokxsZ3dQpRzg4NkD


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Introduced a new configurable random jitter delay feature for place visits, with a default range of 0-750 milliseconds. This adds variable timing to place panel interactions, helping to prevent fixed-interval navigation patterns.
  • Documentation

    • Updated the changelog and configuration documentation to include details about the new jitter delay configuration option.

Closes #25. Adds ScraperConfig::place_panel_jitter (default 750ms): before each
place visit the enrich loop sleeps place_panel_delay plus a random 0..=jitter,
so navigations no longer happen at a fixed interval that bot-detection can flag.

Jitter uses std-only entropy (sub-second wall-clock nanos) via a pure jitter_ms
helper — no new dependency. Duration::ZERO disables it. Unit-tested for bounds
and the zero case.

https://claude.ai/code/session_01TPpTHPokxsZ3dQpRzg4NkD
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Liohtml, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 57 minutes and 17 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0edd2bee-73cc-4079-a6b3-156b5326a36d

📥 Commits

Reviewing files that changed from the base of the PR and between 16a87c5 and 3e86d9a.

📒 Files selected for processing (1)
  • src/lib.rs
📝 Walkthrough

Walkthrough

Adds place_panel_jitter: Duration (default 750 ms) to ScraperConfig. The enrich-path sleep in search_many_on_page now waits place_panel_delay + jitter, where jitter is computed by new internal helpers jitter_ms and time_seed. Tests, README, and CHANGELOG are updated accordingly.

Changes

Per-place jitter delay feature

Layer / File(s) Summary
ScraperConfig field, jitter helpers, and sleep wiring
src/lib.rs
Adds public place_panel_jitter: Duration field (default 750 ms) to ScraperConfig; introduces jitter_ms(seed, max_ms) and time_seed() internal helpers; replaces the fixed place_panel_delay sleep with place_panel_delay + jitter in the enrich loop; adds jitter_within_bounds unit test and updates config_defaults assertion.
CHANGELOG and README documentation
CHANGELOG.md, README.md
Records ScraperConfig::place_panel_jitter in the "Unreleased / Added" CHANGELOG entry and adds a one-line field description to the README configuration table.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 A jitter, a wobble, a randomized hop,
No fixed-interval tapping that bots cannot stop.
Seven-fifty milliseconds of chaos, just right,
Each place panel visit now shrouded from sight.
The seed of the clock blooms to entropy's art —
A rabbit's small tweak with a very stealthy heart! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: implementing randomized jitter for place visit delays, which directly addresses the PR's primary objective.
Linked Issues check ✅ Passed The PR implements all coding requirements from issue #25: adds configurable place_panel_jitter to ScraperConfig, applies random jitter (0..=750ms) to place visit delays, uses pure std-based entropy avoiding external dependencies, includes unit tests, and verifies all checks pass.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing jitter: documentation updates (CHANGELOG.md, README.md) and core implementation (ScraperConfig field, jitter helpers, updated tests in src/lib.rs). No unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/bundle-e-place-jitter

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Address devil's-advocate / code review of Bundle E:
- Seed quality (major): subsec_nanos correlated across the ~1.5s loop and was
  modulo-biased. time_seed now mixes full wall-clock nanos with a process-wide
  call counter through DefaultHasher (SipHash), so seeds are well-distributed
  and never repeat or correlate between successive place visits.
- Guard the Duration::as_millis() u128 -> u64 cast with try_from (saturating).
- Clarify docs: jitter is purely additive (place_panel_delay is the minimum),
  Duration::ZERO disables it, and place_panel_delay cross-references the jitter.

https://claude.ai/code/session_01TPpTHPokxsZ3dQpRzg4NkD

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib.rs`:
- Around line 375-378: The jitter calculation has two issues: first, the call to
jitter_ms at line 377 performs a lossy cast via as_millis() as u64 without
validating the result, and second, the jitter_ms function (around line 644)
performs max_ms + 1 which can overflow when max_ms equals u64::MAX, causing
panics in debug builds. Fix this by validating and clamping the milliseconds
value to a safe range before passing it to jitter_ms, and add explicit bounds
checking inside the jitter_ms function to safely handle the u64::MAX case
instead of blindly adding 1 to max_ms.
- Line 379: In the tokio::time::sleep call, replace the standard addition
operator between self.cfg.place_panel_delay and jitter with saturating_add to
prevent potential overflow panics. This defensive change ensures that when
extreme user-provided duration values are added together, the operation
gracefully clamps to the maximum Duration value instead of panicking, while
preserving the intended sleep behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5b6b33e1-3492-4cd1-b8a9-f1eea5ab7870

📥 Commits

Reviewing files that changed from the base of the PR and between 615bd9e and 16a87c5.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • README.md
  • src/lib.rs

Comment thread src/lib.rs Outdated
Comment thread src/lib.rs
time_seed(),
self.cfg.place_panel_jitter.as_millis() as u64,
));
tokio::time::sleep(self.cfg.place_panel_delay + jitter).await;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use saturating duration addition for defensive runtime safety.

At Line 379, self.cfg.place_panel_delay + jitter can overflow and panic for extreme user-provided durations. saturating_add avoids a hard crash while preserving intent.

Proposed fix
-                tokio::time::sleep(self.cfg.place_panel_delay + jitter).await;
+                tokio::time::sleep(self.cfg.place_panel_delay.saturating_add(jitter)).await;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
tokio::time::sleep(self.cfg.place_panel_delay + jitter).await;
tokio::time::sleep(self.cfg.place_panel_delay.saturating_add(jitter)).await;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib.rs` at line 379, In the tokio::time::sleep call, replace the standard
addition operator between self.cfg.place_panel_delay and jitter with
saturating_add to prevent potential overflow panics. This defensive change
ensures that when extreme user-provided duration values are added together, the
operation gracefully clamps to the maximum Duration value instead of panicking,
while preserving the intended sleep behavior.

@Liohtml
Liohtml merged commit f19897d into main Jun 16, 2026
4 checks passed
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.

[repo-health] Low: no between-place delay in enrich path — sequential place visits have no jitter, increasing bot-detection risk

2 participants