Skip to content
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

Share GlotPress 429 auto retry from ASC metadata to iOS strings download #516

Open
wants to merge 22 commits into
base: trunk
Choose a base branch
from

Conversation

mokagio
Copy link
Contributor

@mokagio mokagio commented Oct 4, 2023

What does it do?

After benefitting from the GlotPress metadata downloads automatically retrying upon receiving a 429, it felt particularly painful, not to mention time consuming, to manually retry when the iOS .strings got a 429.

This PR extracts the "retry upon 429" logic in a dedicated GlotpressDownloader object, and updates the iOS strings and generic metadata download logic to use it.

I added as much test coverage as I could think of to guide my changes, but I didn't try to provide full coverage given the uncertain future of the metadata download component.

Checklist before requesting a review

  • Run bundle exec rubocop to test for code style violations and recommendations
  • Add Unit Tests (aka specs/*_spec.rb) if applicable
  • Run bundle exec rspec to run the whole test suite and ensure all your tests pass
  • Make sure you added an entry in the CHANGELOG.md file to describe your changes under the appropriate existing ### subsection of the existing ## Trunk section.
  • If applicable, add an entry in the MIGRATION.md file to describe how the changes will affect the migration from the previous major version and what the clients will need to change and consider. — N.A.

I thought this might help with an issue I'm experiencing where there the
uri of a stubbed response is unexpectedly nil, but it did not.
@mokagio mokagio force-pushed the mokagio/auto-retry-on-strings-glotpress-429 branch from 28e8f7c to d35d027 Compare October 5, 2023 05:10
context 'when GlotPress returs a 200 code' do
it 'returns the response, without retrying' do
downloader = described_class.new(auto_retry: true)
fake_url = 'https://test.com'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

fake_url is misleading... dummy_url might be better?

Copy link
Contributor

Choose a reason for hiding this comment

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

agreed

require 'spec_helper'

describe Fastlane::Helper::MetadataDownloader do
describe 'downloading from GlotPress' do
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test would benefit with ensuring the files are saved.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I'm following, isn't it was those tests already do, by using an in_tmp_dir then testing expect(File.read(destination_path_with_locale)).to eq(…)?

@mokagio mokagio marked this pull request as ready for review October 6, 2023 03:26
3.2.2
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This and the WebMock update were attempts to solve the tests having a missing uri in the stubbed response.

That turned out to be a bug in WebMock (see spec_helper diff). I decided to keep them because they don't seem to hurt, but I can remove this one if you think it should be a changed for a dedicated PR.

Comment on lines -172 to +188
IO.copy_stream(uri.open(options), destination)
IO.copy_stream(StringIO.new(response.body), destination)
Copy link
Contributor

Choose a reason for hiding this comment

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

iirc, the reason I initially used IO.copy_stream was because uri.open happened to be a stream in the first place, and as such this would allow memory optimization (i.e. to avoid having to read the whole, large file content into memory all at once only to write it to the destination file in one block, and instead use copy_stream to write data to the destination as it arrived from the socket).

Now that we don't use uri.open anymore, I'm not sure it makes sense to continue using copy_stream then wrapping the whole response body inside a StringIO.new. I think we can probably instead:

  • Either just use File.write(destination, response.body) directly (which means we lose the memory footprint optimization of write-as-you-receive that copy_stream had, but is it a big deal?)
  • Or try using something like File.open(destination, mode: 'w') { |file| response.read_body(file) } (which I didn't try, but based on this doc I think that's how we'd be supposed to use it?) to still benefit from the "write-as-you-receive" behavior that would allow reducing the memory footprint for very large files.

wdyt?

context 'when GlotPress returs a 200 code' do
it 'returns the response, without retrying' do
downloader = described_class.new(auto_retry: true)
fake_url = 'https://test.com'
Copy link
Contributor

Choose a reason for hiding this comment

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

agreed

Comment on lines +11 to +12
auto_retry_sleep_time: 20,
auto_retry_max_attempts: 30
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
auto_retry_sleep_time: 20,
auto_retry_max_attempts: 30
auto_retry_sleep_time: AUTO_RETRY_SLEEP_TIME,
auto_retry_max_attempts: MAX_AUTO_RETRY_ATTEMPTS

require 'spec_helper'

describe Fastlane::Helper::MetadataDownloader do
describe 'downloading from GlotPress' do
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I'm following, isn't it was those tests already do, by using an in_tmp_dir then testing expect(File.read(destination_path_with_locale)).to eq(…)?

end
end

context 'when GlotPress returs a 429 code' do
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
context 'when GlotPress returs a 429 code' do
context 'when GlotPress returns a 429 code' do

end
end

context 'when GlotPress returs a 429 code' do
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
context 'when GlotPress returs a 429 code' do
context 'when GlotPress returns a 429 code' do

end

context 'when auto retry is disabled' do
context 'when GlotPress returs a 200 code' do
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
context 'when GlotPress returs a 200 code' do
context 'when GlotPress returns a 200 code' do

end
end

context 'when GlotPress returs a 429 code' do
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
context 'when GlotPress returs a 429 code' do
context 'when GlotPress returns a 429 code' do

describe Fastlane::Helper::GlotpressDownloader do
describe 'downloading' do
context 'when auto retry is enabled' do
context 'when GlotPress returs a 200 code' do
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
context 'when GlotPress returs a 200 code' do
context 'when GlotPress returns a 200 code' do

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.

3 participants