copy_tuner_client 0.20.1 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c80d48f19698dd5ffc3d27fc3b5a96d1a9b0ab6761f2eb3a4f7ff37463582bd1
4
- data.tar.gz: 41c817b39c822106a04bcd4cffa4b8a50bc14cfd88b7e677f532987a2c293e62
3
+ metadata.gz: a06b43d1cbb58dfca8f7e340a52e0533cb1398b20e966702822ee90f3253515c
4
+ data.tar.gz: a751f0743edb5dc80802d08647c3ebeca82809f5034b6b14177d607f57c247bb
5
5
  SHA512:
6
- metadata.gz: 55829ac0315b780958a1023339be01bb4750148b9a5d47b0b09bc980e7d5cf84d65aeb07c16ab68ec4e3e1c1361aad2d337e5f297af5df9abafd35b85bed0480
7
- data.tar.gz: 858d7ea50128bd9079f3d8b35fd73910a821a3660de2336c1706129547b8f37492c95cbf4e8a31970dc3ac0985590f0de927019f537902ef17ccccce8b466b58
6
+ metadata.gz: 4f9de9656e80ff2ee79385663e60deecb0df8b3f0f5aa9f5a226dd60b1e1bc92dc287b522e04fcd8ced28fa5e37e98de112e0688ed3bbcdc0719bde21a554bc0
7
+ data.tar.gz: ff0f9f4f2fc05b37fcfe5395db70615fc4c8c019db48858c8e1c799faa907e35916e636a4fda0f6a91410d1db3b6a9b3f1e44ca731ca81faf3a491ef64cba4a6
@@ -4,4 +4,8 @@
4
4
  },
5
5
  "typescript.tsdk": "node_modules/typescript/lib",
6
6
  "typescript.preferences.importModuleSpecifier": "non-relative",
7
+ "rubocop.mode": "disable",
8
+ "cSpell.words": [
9
+ "mkpath"
10
+ ],
7
11
  }
@@ -8,6 +8,10 @@ module CopyTunerClient
8
8
  #
9
9
  # Responsible for locking down access to data used by both threads.
10
10
  class Cache
11
+ STATUS_NOT_READY = :not_ready
12
+ STATUS_PENDING = :pending
13
+ STATUS_READY = :ready
14
+
11
15
  # Usually instantiated when {Configuration#apply} is invoked.
12
16
  # @param client [Client] the client used to fetch and upload data
13
17
  # @param options [Hash]
@@ -25,8 +29,7 @@ module CopyTunerClient
25
29
  @blurbs = {}
26
30
  @blank_keys = Set.new
27
31
  @queued = {}
28
- @started = false
29
- @downloaded = false
32
+ @status = STATUS_NOT_READY
30
33
  end
31
34
 
32
35
  # Returns content for the given blurb.
@@ -97,23 +100,23 @@ module CopyTunerClient
97
100
  end
98
101
 
99
102
  def download
100
- @started = true
103
+ @status = STATUS_PENDING unless ready?
101
104
 
102
- res = client.download do |downloaded_blurbs|
105
+ res = client.download(cache_fallback: pending?) do |downloaded_blurbs|
103
106
  blank_blurbs, blurbs = downloaded_blurbs.partition { |_key, value| value == '' }
104
107
  lock do
105
- @blank_keys = Set.new(blank_blurbs.to_h.keys)
108
+ @blank_keys = Set.new(blank_blurbs.map(&:first))
106
109
  @blurbs = blurbs.to_h
107
110
  end
108
111
  end
109
112
 
110
113
  @last_downloaded_at = Time.now.utc
114
+ @status = STATUS_READY unless ready?
111
115
 
112
116
  res
113
117
  rescue ConnectionError => e
114
118
  logger.error e.message
115
- ensure
116
- @downloaded = true
119
+ raise e unless ready?
117
120
  end
118
121
 
119
122
  # Downloads and then flushes
@@ -129,7 +132,11 @@ module CopyTunerClient
129
132
  end
130
133
 
131
134
  def pending?
132
- @started && !@downloaded
135
+ @status == STATUS_PENDING
136
+ end
137
+
138
+ def ready?
139
+ @status == STATUS_READY
133
140
  end
134
141
 
135
142
  private
@@ -29,10 +29,16 @@ module CopyTunerClient
29
29
  # @option options [Logger] :logger where to log transactions
30
30
  # @option options [String] :ca_file path to root certificate file for ssl verification
31
31
  def initialize(options)
32
+ @etag = nil
33
+ @downloaded_blurbs = {}
34
+
32
35
  [:api_key, :host, :port, :public, :http_read_timeout,
33
- :http_open_timeout, :secure, :logger, :ca_file, :s3_host].each do |option|
36
+ :http_open_timeout, :secure, :logger, :ca_file, :s3_host, :download_cache_dir].each do |option|
34
37
  instance_variable_set "@#{option}", options[option]
35
38
  end
39
+
40
+ @download_cache_dir.mkpath
41
+ load_cachedata(last_download_path)
36
42
  end
37
43
 
38
44
  # Downloads all blurbs for the given api_key.
@@ -45,7 +51,7 @@ module CopyTunerClient
45
51
  #
46
52
  # @yield [Hash] downloaded blurbs
47
53
  # @raise [ConnectionError] if the connection fails
48
- def download
54
+ def download(cache_fallback: false)
49
55
  connect(s3_host) do |http|
50
56
  request = Net::HTTP::Get.new(uri(download_resource))
51
57
  request['If-None-Match'] = @etag
@@ -53,15 +59,18 @@ module CopyTunerClient
53
59
  t = Time.now
54
60
  response = http.request(request)
55
61
  t_ms = ((Time.now - t) * 1000).to_i
56
- if check response
62
+ downloaded = check(response)
63
+ if downloaded
57
64
  # NOTE: Net::HTTPではgzipが透過的に扱われるため正確なファイルサイズや速度をログに出すのは難しい
58
65
  log "Downloaded translations (#{t_ms}ms)"
59
- yield JSON.parse(response.body)
66
+ @downloaded_blurbs = JSON.parse(response.body)
67
+ @etag = response['ETag']
68
+ last_download_path.write(JSON.pretty_generate(etag: @etag, downloaded_blurbs: @downloaded_blurbs))
60
69
  else
61
70
  log "No new translations (#{t_ms}ms)"
62
71
  end
63
72
 
64
- @etag = response['ETag']
73
+ yield(@downloaded_blurbs) if downloaded || cache_fallback
65
74
  end
66
75
  end
67
76
 
@@ -107,6 +116,21 @@ module CopyTunerClient
107
116
  end
108
117
  end
109
118
 
119
+ def last_download_path
120
+ @download_cache_dir.join("last-download-#{download_resource}")
121
+ end
122
+
123
+ def load_cachedata(pathname)
124
+ return unless pathname.exist?
125
+
126
+ cache = JSON.parse(pathname.read.to_s).transform_keys(&:to_sym)
127
+ @etag = cache[:etag]
128
+ @downloaded_blurbs = cache[:downloaded_blurbs]
129
+ log "Loaded cache data from #{pathname}"
130
+ rescue JSON::JSONError, Errno::ENOENT, Errno::ENOTDIR
131
+ nil
132
+ end
133
+
110
134
  def connect(host)
111
135
  http = Net::HTTP.new(host, port)
112
136
  http.open_timeout = http_open_timeout
@@ -18,7 +18,8 @@ module CopyTunerClient
18
18
  proxy_port proxy_user secure polling_delay sync_interval
19
19
  sync_interval_staging sync_ignore_path_regex logger
20
20
  framework middleware disable_middleware disable_test_translation
21
- ca_file exclude_key_regexp s3_host locales ignored_keys ignored_key_handler].freeze
21
+ ca_file exclude_key_regexp s3_host locales ignored_keys ignored_key_handler
22
+ download_cache_dir].freeze
22
23
 
23
24
  # @return [String] The API key for your project, found on the project edit form.
24
25
  attr_accessor :api_key
@@ -139,6 +140,9 @@ module CopyTunerClient
139
140
  # @return [Integer] The project id
140
141
  attr_accessor :project_id
141
142
 
143
+ # @return [Pathname] The directory to cache downloaded files
144
+ attr_accessor :download_cache_dir
145
+
142
146
  alias secure? secure
143
147
 
144
148
  # Instantiated from {CopyTunerClient.configure}. Sets defaults.
@@ -164,6 +168,7 @@ module CopyTunerClient
164
168
  self.ignored_keys = []
165
169
  self.ignored_key_handler = ->(e) { raise e }
166
170
  self.project_id = nil
171
+ self.download_cache_dir = Pathname.new(Dir.pwd).join('tmp', 'cache', 'copy_tuner_client')
167
172
 
168
173
  @applied = false
169
174
  end
@@ -13,8 +13,9 @@ module CopyTunerClient
13
13
  else
14
14
  ::Rails.logger
15
15
  end
16
- config.framework = "Rails: #{::Rails::VERSION::STRING}"
17
- config.middleware = ::Rails.configuration.middleware
16
+ config.framework = "Rails: #{::Rails::VERSION::STRING}"
17
+ config.middleware = ::Rails.configuration.middleware
18
+ config.download_cache_dir = ::Rails.root.join('tmp', 'cache', 'copy_tuner_client')
18
19
  end
19
20
  end
20
21
 
@@ -1,6 +1,6 @@
1
1
  module CopyTunerClient
2
2
  # Client version
3
- VERSION = '0.20.1'.freeze
3
+ VERSION = '0.21.0'.freeze
4
4
 
5
5
  # API version being used to communicate with the server
6
6
  API_VERSION = '2.0'.freeze
@@ -3,10 +3,13 @@ require 'spec_helper'
3
3
  describe CopyTunerClient::Cache do
4
4
  let(:client) { FakeClient.new }
5
5
 
6
- def build_cache(config = {})
6
+ def build_cache(ready: false, **config)
7
+ config[:client] ||= client
7
8
  config[:logger] ||= FakeLogger.new
8
9
  default_config = CopyTunerClient::Configuration.new.to_hash
9
- CopyTunerClient::Cache.new(client, default_config.update(config))
10
+ cache = CopyTunerClient::Cache.new(client, default_config.update(config))
11
+ cache.instance_variable_set(:@status, CopyTunerClient::Cache::STATUS_READY) if ready
12
+ cache
10
13
  end
11
14
 
12
15
  it 'provides access to downloaded data' do
@@ -143,7 +146,7 @@ describe CopyTunerClient::Cache do
143
146
  failure = 'server is napping'
144
147
  logger = FakeLogger.new
145
148
  expect(client).to receive(:download).and_raise(CopyTunerClient::ConnectionError.new(failure))
146
- cache = build_cache(logger: logger)
149
+ cache = build_cache(logger: logger, ready: true)
147
150
 
148
151
  cache.download
149
152
 
@@ -169,31 +172,6 @@ describe CopyTunerClient::Cache do
169
172
  expect(t_wait.join(1)).not_to be_nil
170
173
  end
171
174
 
172
- it "doesn't block if the first download fails" do
173
- client.delay = true
174
- client.error = StandardError.new('Failure')
175
- cache = build_cache
176
-
177
- error = nil
178
- t_download = Thread.new do
179
- begin
180
- cache.download
181
- rescue StandardError => e
182
- error = e
183
- end
184
- end
185
- sleep 0.1 until cache.pending?
186
-
187
- t_wait = Thread.new do
188
- cache.wait_for_download
189
- end
190
- client.go
191
- expect(t_download.join(1)).not_to be_nil
192
- expect(error).to be_kind_of(StandardError)
193
- expect(t_wait.join(1)).not_to be_nil
194
- expect { cache.download }.to raise_error(StandardError, 'Failure')
195
- end
196
-
197
175
  it "doesn't block before downloading" do
198
176
  logger = FakeLogger.new
199
177
  cache = build_cache(logger: logger)
@@ -1,8 +1,15 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe CopyTunerClient do
4
+ let(:download_cache_dir) { Pathname.new(Dir.mktmpdir('copy_tuner_client')) }
5
+
6
+ after do
7
+ FileUtils.rm_rf(download_cache_dir)
8
+ end
9
+
4
10
  def build_client(config = {})
5
11
  config[:logger] ||= FakeLogger.new
12
+ config[:download_cache_dir] = download_cache_dir
6
13
  default_config = CopyTunerClient::Configuration.new.to_hash
7
14
  default_config[:s3_host] = 'copy-tuner.com'
8
15
  client = CopyTunerClient::Client.new(default_config.update(config))
@@ -16,7 +16,7 @@ class FakeClient
16
16
  @data[key] = value
17
17
  end
18
18
 
19
- def download
19
+ def download(cache_fallback: false)
20
20
  wait_for_delay
21
21
  raise_error_if_present
22
22
  @downloads += 1
@@ -62,4 +62,3 @@ class FakeClient
62
62
  end
63
63
  end
64
64
  end
65
-
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: copy_tuner_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.1
4
+ version: 0.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SonicGarden
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-04-28 00:00:00.000000000 Z
11
+ date: 2025-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n