Skip to content

Retry: sleep_for_retry uses max(wait, delay_max) — inflates small Retry-After to delay_max (60s floor) (#860)#867

Closed
peco-engineer-bot[bot] wants to merge 2 commits into
mainfrom
ai/issue-860
Closed

Retry: sleep_for_retry uses max(wait, delay_max) — inflates small Retry-After to delay_max (60s floor) (#860)#867
peco-engineer-bot[bot] wants to merge 2 commits into
mainfrom
ai/issue-860

Conversation

@peco-engineer-bot

Copy link
Copy Markdown
Contributor

Summary

Automated fix for #860 — Retry: sleep_for_retry uses max(wait, delay_max) — inflates small Retry-After to delay_max (60s floor).

Changed proposed_wait = max(proposed_wait, self.delay_max) to min(...) in DatabricksRetryPolicy.sleep_for_retry (src/databricks/sql/auth/retry.py:300) so delay_max acts as a ceiling on the honored Retry-After / backoff wait rather than a floor, matching the sibling get_backoff_time. The three reproducing tests now pass and the full unit suite stays green.

Root cause & plan

Root cause: In src/databricks/sql/auth/retry.py, DatabricksRetryPolicy.sleep_for_retry (line 300) computes proposed_wait = max(proposed_wait, self.delay_max). This uses delay_max as a FLOOR rather than a CEILING, so any proposed wait smaller than delay_max (default 60s) is inflated up to delay_max. This inverts the intent documented on the sibling get_backoff_time, which correctly clamps with min(proposed_backoff, self.delay_max). Because this overridden sleep_for_retry always sleeps and returns True, it governs BOTH the server Retry-After path and the exponential-backoff (no-header) path — so a Retry-After: 2 becomes a 60s sleep, and a 1s backoff also becomes a 60s sleep. Fix: change max to min so delay_max caps the wait.
Files: src/databricks/sql/auth/retry.py, tests/unit/test_retry.py
Planned coverage:

  • A small server Retry-After header (e.g. Retry-After: 2) must be honored as ~2s, not inflated to delay_max. Construct an HTTPResponse(status=503, headers={'Retry-After':'2'}), call retry_policy.sleep(response) with time.sleep patched, and assert time.sleep was called with 2 (min(2, delay_max)), not delay_max. Fails today (asserts 2, gets delay_max=30). (Retry-After header used as ceiling, not floor)
  • The no-Retry-After exponential backoff path must sleep the true backoff (min(backoff, delay_max)), not be inflated to delay_max. Update the two existing tests (test_sleep__no_retry_after, test_sleep__no_retry_after_header__multiple_retries) that currently assert the buggy max(backoff, delay_max)=delay_max, to assert min(...) i.e. the real backoff value. (Exponential-backoff path inflated to delay_max floor)

Files changed

  • src/databricks/sql/auth/retry.py
  • tests/unit/test_retry.py

Test plan

  • tests/unit/test_retry.py::TestRetry::test_sleep__retry_after_header_honored_not_inflated — fails (red) against the original code, passes (green) after the fix
  • tests/unit/test_retry.py::TestRetry::test_sleep__no_retry_after — fails (red) against the original code, passes (green) after the fix
  • tests/unit/test_retry.py::TestRetry::test_sleep__no_retry_after_header__multiple_retries — fails (red) against the original code, passes (green) after the fix

🤖 Generated by engineer-bot (bug-fix flow) — review before merge.

eric-wang-1990 and others added 2 commits July 16, 2026 17:36
…publish

The engineer-bot author run on issue #860 failed at "Open / update fix PR":
publish's leftover safety-net found poetry.lock + pyproject.toml unstaged and
not in the agent's touched_files, so it refused to open the PR — even though the
agent's fix + tests were correct (494 passed).

Root cause: the shared setup-poetry action runs `poetry lock` (to reconcile the
lock with the internal JFrog source it injects), which REWRITES the tracked
poetry.lock / pyproject.toml in the working tree. That churn is harmless for the
5 real-CI consumers of the action (they commit nothing) but poisons the two
engineer-bot workflows, which publish a PR from the working tree.

Fix (engineer-bot side only — leave the shared action untouched): after the
Poetry setup, `git checkout -- poetry.lock pyproject.toml` to drop the churn once
the venv is built, so only the agent's edits remain in the tree at publish time.
Applied to both engineer-bot.yml (author) and engineer-bot-followup.yml.

Signed-off-by: eric-wang-1990 <e.wang@databricks.com>
Co-authored-by: Isaac
…ry-After to delay_max (60s floor) (#860)

Signed-off-by: peco-engineer-bot[bot] <3815206+peco-engineer-bot[bot]@users.noreply.github.com>
@peco-engineer-bot peco-engineer-bot Bot added the engineer-bot Maintainer-applied gate: triggers engineer-bot (bug-fix on issue / take-over on PR). label Jul 17, 2026

@peco-review-bot peco-review-bot 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.

✅ No issues identified by the review bot.

@eric-wang-1990

Copy link
Copy Markdown
Contributor

This is a test PR, close for now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

engineer-bot Maintainer-applied gate: triggers engineer-bot (bug-fix on issue / take-over on PR).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant