-
Notifications
You must be signed in to change notification settings - Fork 206
SG-41115 more changes #426
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
base: ticket/SG-41115-minor-changes
Are you sure you want to change the base?
SG-41115 more changes #426
Conversation
Also unify the loop and attempts code accross all methods
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR refactors the retry logic for RPC calls and data uploads in the Shotgun API client. The changes centralize retry configuration by removing hardcoded constants and using configuration-based retry parameters instead.
Key changes:
- Replace hardcoded
MAX_ATTEMPTSandBACKOFFconstants with configurablemax_rpc_attemptsandrpc_attempt_intervalfrom the config object - Standardize retry loop implementation across
_call_rpc,_make_call,_upload_data_to_storage, and_send_formmethods - Add SSL error handling with detailed logging in
_upload_data_to_storage
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| attempt = 0 | ||
| while attempt < max_rpc_attempts: | ||
| if attempt: | ||
| time.sleep(attempt * rpc_attempt_interval) | ||
|
|
||
| attempt += 1 | ||
|
|
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sleep duration calculation multiplies attempt * rpc_attempt_interval, but attempt starts at 0 and increments to 1 before the first iteration's logic. This means the first retry (after a failure) will sleep for 1 * rpc_attempt_interval, the second retry for 2 * rpc_attempt_interval, etc. However, in the old code, the sleep was attempt * BACKOFF where attempt started at 1, giving the same progression. The issue is that when attempt reaches max_rpc_attempts, the loop exits, but the last attempt number logged will be max_rpc_attempts. If max_rpc_attempts is 3, you'll see attempts 1, 2, 3, but only 3 actual iterations (0->1, 1->2, 2->3 before exit). This is correct behavior, but the new loop condition attempt < max_rpc_attempts with attempt starting at 0 means if max_rpc_attempts is 3, you get attempts numbered 1, 2, 3 (three attempts total), which matches the old behavior where MAX_ATTEMPTS = 3 gave attempts 1, 2, 3. No issue here on second thought, but worth verifying the intent is the same number of attempts.
| attempt = 0 | |
| while attempt < max_rpc_attempts: | |
| if attempt: | |
| time.sleep(attempt * rpc_attempt_interval) | |
| attempt += 1 | |
| for attempt in range(1, max_rpc_attempts + 1): | |
| if attempt > 1: | |
| time.sleep((attempt - 1) * rpc_attempt_interval) |
| max_rpc_attempts = self.config.max_rpc_attempts | ||
| rpc_attempt_interval = self.config.rpc_attempt_interval / 1000.0 | ||
|
|
||
| while attempt <= max_rpc_attempts: |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent loop condition: this uses attempt <= max_rpc_attempts while other retry loops in the same file use attempt < max_rpc_attempts (lines 3762, 3925, 4655). If max_rpc_attempts is 3, this loop will execute 4 times (attempt values 1, 2, 3, 4), while the others execute 3 times. This should be attempt < max_rpc_attempts for consistency.
| while attempt <= max_rpc_attempts: | |
| while attempt < max_rpc_attempts: |
|
|
||
| attempt = 1 | ||
| while attempt <= self.MAX_ATTEMPTS: | ||
| ## TODO - add unitests for those cases |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected spelling of 'unitests' to 'unittests'.
| ## TODO - add unitests for those cases | |
| ## TODO - add unittests for those cases |
| if attempt == max_rpc_attempts: | ||
| LOG.debug("Request failed. Giving up after %d attempts." % attempt) | ||
| raise | ||
| # TODO create only one attempt for SSL errors. |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This TODO comment is unclear about what 'create only one attempt' means. Consider rephrasing to something like 'TODO: Skip retries for SSL errors' or 'TODO: Fail immediately on SSL errors without retrying' to clarify the intended behavior.
| # TODO create only one attempt for SSL errors. | |
| # TODO: Fail immediately on SSL errors without retrying. |
| return value | ||
|
|
||
|
|
||
| def safe_short_url(url: str, max_path_length: int = 80) -> str: |
Copilot
AI
Nov 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The safe_short_url function lacks a docstring. Given its purpose of sanitizing URLs for logging (removing credentials and truncating paths), a docstring would improve maintainability by explaining the security and formatting rationale.
| def safe_short_url(url: str, max_path_length: int = 80) -> str: | |
| def safe_short_url(url: str, max_path_length: int = 80) -> str: | |
| """ | |
| Sanitize a URL for safe logging by removing sensitive information and truncating long paths. | |
| This function removes credentials (such as HTTP Basic Auth usernames/passwords and API keys) | |
| from the URL, strips query parameters and fragments, and truncates the path if it exceeds | |
| `max_path_length` by replacing the middle part with '[...]'. This helps prevent accidental | |
| exposure of sensitive data in logs or error messages. | |
| Args: | |
| url (str): The URL to sanitize. | |
| max_path_length (int): Maximum allowed length for the path component. Defaults to 80. | |
| Returns: | |
| str: The sanitized, shortened URL safe for logging. | |
| """ |
TODO