Skip to content

fix: wait retry_interval_seconds between retries (#140) - #141

Open
jaideeppyne wants to merge 1 commit into
typesense:masterfrom
jaideeppyne:fix/retry-interval-delay
Open

fix: wait retry_interval_seconds between retries (#140)#141
jaideeppyne wants to merge 1 commit into
typesense:masterfrom
jaideeppyne:fix/retry-interval-delay

Conversation

@jaideeppyne

Copy link
Copy Markdown

Summary

Fixes #140.

Since the v1.0.0 httpx rewrite, the client no longer waits between retries. _execute_request (sync and async) recurses straight into the next attempt on a server error, so retry_interval_seconds is stored but never read. A node returning 503 or timing out receives every attempt within a few milliseconds instead of being spaced out — and because each failed attempt marks the node unhealthy, all retries land before the node has any chance to recover. The 0.21.0 client slept via time.sleep(self.config.retry_interval_seconds).

Changes

  • Restore the delay in both sync/api_call.py and async_/api_call.py, sleeping only between attempts (num_retries < config.num_retries) so there is no needless wait before the final failure is raised — this reproduces the "N+1 attempts / N gaps" behaviour the issue documents.
  • Fix the related config-key mismatch flagged in the issue: retry_interval_seconds is read by Configuration but was missing from ConfigDict (so the working key failed type-checking), while the documented interval_seconds was in ConfigDict but read by nothing. Add retry_interval_seconds to ConfigDict and honour both spellings — the same shape as the connection_timeout_seconds fix in [bug] typesense.configuration.ConfigDict is missing parameter connection_timeout_seconds #73.
  • The async client is the unasync source of truth; add an asyncio → time token mapping in utils/run-unasync.py so the generated sync client uses time.sleep.

Tests

Adds test_sleeps_retry_interval_between_retries and its async counterpart, which assert the client waits retry_interval_seconds between failed attempts. Both fail on master (no delay occurs) and pass with this change.

The httpx rewrite (v1.0.0) dropped the delay between retries that the
requests-based client had. `_execute_request` recursed straight into the
next attempt on a server error, so `retry_interval_seconds` was stored but
never read. A node returning 503 or timing out received all attempts within
milliseconds instead of being spaced out, and since each failed attempt marks
the node unhealthy, every retry landed before the node had any chance to
recover.

Restore the wait in both the sync and async clients, sleeping only between
attempts (num_retries < config.num_retries) so there is no needless delay
before the final failure is raised.

Also address the related config-key mismatch: `retry_interval_seconds` was
read by Configuration but absent from ConfigDict (so the working key failed
type checking), while the documented `interval_seconds` was in ConfigDict but
never read. Add `retry_interval_seconds` to ConfigDict and honor both
spellings, mirroring the earlier fix for `connection_timeout_seconds` (typesense#73).

The async client is the unasync source of truth; add an asyncio->time token
mapping so the generated sync client uses `time.sleep`.

Adds regression tests for both the sync and async retry paths.

@tharropoulos tharropoulos left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM :shipit:

CC: @kishorenc

@jaideeppyne

Copy link
Copy Markdown
Author

Gentle nudge, and no urgency.

Thanks for the review @tharropoulos. @kishorenc, this is ready whenever it suits you. Happy to rebase or adjust anything if that would help.

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.

retry_interval_seconds is stored but never used, so retries fire with no delay (regression from 0.21.0)

2 participants