-
Couldn't load subscription status.
- Fork 61
Faster upload token refresh on 5xx errors during uploads #548
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
Open
ppolewicz
wants to merge
2
commits into
master
Choose a base branch
from
refresh_token_faster_if_503_during_upload
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Refresh upload tokens faster when server responds with 5xx during an upload attempt. Fixes [B2_Command_Line_Tool#1118](https://github.com/Backblaze/B2_Command_Line_Tool/issues/1118) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| ###################################################################### | ||
| # | ||
| # File: test/unit/test_upload_503_token_refresh.py | ||
| # | ||
| # Copyright 2025 Backblaze Inc. All Rights Reserved. | ||
| # | ||
| # License https://www.backblaze.com/using_b2_code.html | ||
| # | ||
| ###################################################################### | ||
| """ | ||
| Test to verify that upload tokens are refreshed when a 503 error is returned. | ||
| This test simulates the scenario where a server returns a 503 Service Unavailable | ||
| error during file upload and verifies that the SDK properly requests new upload | ||
| tokens for subsequent retry attempts. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from unittest.mock import patch | ||
|
|
||
| from b2sdk._internal.exception import ServiceError | ||
| from b2sdk.v3 import B2Api, B2HttpApiConfig, DummyCache, RawSimulator, StubAccountInfo | ||
|
|
||
| from .test_base import TestBase | ||
|
|
||
|
|
||
| class TestUpload503TokenRefresh(TestBase): | ||
| """Test that 503 errors trigger upload token refresh using RawSimulator""" | ||
|
|
||
| def setUp(self): | ||
| self.bucket_name = 'test-bucket' | ||
| self.account_info = StubAccountInfo() | ||
| self.api = B2Api( | ||
| self.account_info, | ||
| cache=DummyCache(), | ||
| api_config=B2HttpApiConfig(_raw_api_class=RawSimulator), | ||
| ) | ||
| self.simulator = self.api.session.raw_api | ||
| (self.account_id, self.master_key) = self.simulator.create_account() | ||
| self.api.authorize_account( | ||
| application_key_id=self.account_id, | ||
| application_key=self.master_key, | ||
| realm='production', | ||
| ) | ||
| self.bucket = self.api.create_bucket(self.bucket_name, 'allPublic') | ||
|
|
||
| def test_upload_503_triggers_token_refresh(self): | ||
| """ | ||
| Test that when a 503 error occurs during upload, the SDK: | ||
| 1. Retries the upload | ||
| 2. Uses a different upload token for the retry | ||
| """ | ||
| # Track upload URLs/tokens used during upload attempts | ||
| upload_urls_used = [] | ||
|
|
||
| # Wrap the upload_file method to track upload URLs | ||
| original_upload_file = self.simulator.upload_file | ||
|
|
||
| def tracked_upload_file(upload_url, *args, **kwargs): | ||
| upload_urls_used.append(upload_url) | ||
| return original_upload_file(upload_url, *args, **kwargs) | ||
|
|
||
| # Inject a 503 error for the first upload attempt | ||
| self.simulator.set_upload_errors( | ||
| [ServiceError('503 service_unavailable Service Unavailable')] | ||
| ) | ||
|
|
||
| # Patch upload_file to track URLs | ||
| with patch.object(self.simulator, 'upload_file', side_effect=tracked_upload_file): | ||
| # Perform upload - should fail once with 503, then retry and succeed | ||
| data = b'test data for 503 error scenario' | ||
| file_name = 'test_503.txt' | ||
|
|
||
| self.bucket.upload_bytes(data, file_name) | ||
|
|
||
| # Verify the upload succeeded | ||
| file_info = self.bucket.get_file_info_by_name(file_name) | ||
| assert file_info is not None | ||
|
|
||
| # Verify that at least 2 upload attempts were made | ||
| assert ( | ||
| len(upload_urls_used) >= 2 | ||
| ), f'Expected at least 2 upload attempts, but got {len(upload_urls_used)}' | ||
|
|
||
| # Extract auth tokens from the URLs | ||
| # URL format: https://upload.example.com/bucket_id/upload_id/auth_token | ||
| first_url = upload_urls_used[0] | ||
| second_url = upload_urls_used[1] | ||
|
|
||
| first_auth_token = first_url.split('/')[-1] | ||
| second_auth_token = second_url.split('/')[-1] | ||
|
|
||
| print('\n✓ Upload token refresh test results:') | ||
| print(f' First URL: {first_url}') | ||
| print(f' Second URL: {second_url}') | ||
| print(f' First auth token: {first_auth_token}') | ||
| print(f' Second auth token: {second_auth_token}') | ||
| print(f' Total upload attempts: {len(upload_urls_used)}') | ||
|
|
||
| # Verify that auth tokens are different after a 503 error. | ||
| # This confirms that the SDK properly clears cached upload tokens | ||
| # and requests fresh ones when a 503 Service Error occurs. | ||
| assert first_auth_token != second_auth_token, ( | ||
| f'BUG: Auth tokens are the same after 503 error!\n' | ||
| f'Expected different auth tokens, but got:\n' | ||
| f' First: {first_auth_token}\n' | ||
| f' Second: {second_auth_token}\n' | ||
| f'This indicates the SDK is cycling through pre-fetched upload URLs\n' | ||
| f'instead of requesting fresh upload tokens after a 503 error.' | ||
| ) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 method
post_content_return_jsonis being called by_post_json_return_json, and the latter is being used by almost all post requests.I am afraid this will break retries for all POST requests, not just ones related to uploads.
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.
Yeah that would be terrible. Please make sure we have tests for this (I assumed that we do and that the fact that the tests pass after the fix means it's ok, but maybe not?)