shopify_unlimited 0.0.13.threadsafe → 0.0.14.threadsafe

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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MWZmMDAyMjRlNjFkMDAxZTg1MDE1OGYzNWVhYmI1NmRlYjQ5OTBiYw==
4
+ MGJhYTI2MWQ4NjQxNjNlODZmN2I3ZTY3MjEzZGQ0MjIxZGZhZDI2ZQ==
5
5
  data.tar.gz: !binary |-
6
- MDQyNTNhMTc0ZGI0NDNhZWUyYWM1ZDQ4ZTFlYTdlNDE0ZTY3MGI0YQ==
6
+ ZTQzMDliNDE3MGZmY2RiY2E5OTRjYjdkZDRmZjYwNjZhNDQ2ZmE4Yw==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- N2M0NGQ4ODk5YTU5ZDcxYTU4ZGVlNTFjNmE2ZTdhMmU0YzEyMGE4OTU3ZDUy
10
- ZjEwZmJkMzQ4ZjgxOTMyMjJlNjFlMmI3MTIxYzM3ZTA0ZWQzNzkzODhhN2Rh
11
- NWY1OWE1NjZiNTFjNDU4NjMyNmNlYjJkMmQzYjM5MWRjYTBjMzg=
9
+ NjgyNzMxMTE5NWIyOGQxODAyNWI4YTdkZGUwZjBiNTQwOWQzMWJhZDRiYjNk
10
+ MzA3MDI3YTJiOGI4YjNiODRjN2FlNDAxMjI5NTRhNzE5ODVlYTU3NjhmNWRj
11
+ MDRjN2RkNmFiNzc1YjRiMWJlN2UwY2QyZTQyMzdlM2U2OWZiNDI=
12
12
  data.tar.gz: !binary |-
13
- NWE3NTc1YzFlMGQxYjM5ZWZiNDAyZDU2Y2EzMDhiNzdjYzYzNDA1MjQ2NWE0
14
- ZmU0YTg2YTI4NWZhNzE4ZDJkYTVjN2JkZDhkYzVlMzdmYjNlYmY1NWY5Zjgz
15
- N2ZkYjYwMTE1YjI3MmU2OWRjNmFkY2UxMjVlMzEwMjlmMTA5N2I=
13
+ ZWE3MjM3ODk3NmY3ZGYzNDZjYzI4ZjU4OGZhNGNmNzU1ZGFkNDk1ZDIwYWFj
14
+ MjE5OGE2ZjBiNjM1YzFkMjk4NmJhMjQ4YTRhNjVlNWQ3YzU0NTg1MzQzMDY4
15
+ ZWQxZDEwNzlkMDRjMjc0ZDhiMGMzMjdlYzZlZGM0MzhhNDM5MWU=
@@ -38,15 +38,18 @@ module ActiveResource
38
38
  page = 0
39
39
  # as long as the number of results we got back is not less than the limit we (probably) have more to fetch
40
40
  while( (results.count - last_count) >= limit) do
41
- raise ShopifyAPI::Limits::Error.new if ShopifyAPI.credit_maxed?
42
41
  page +=1
43
42
  last_count = results.count
44
43
  options[:params][:page] = page
45
- results.concat find_every.bind(self).call(options)
44
+ ShopifyAPI::Shop.current.throttle.run do
45
+ results.concat find_every.bind(self).call(options)
46
+ end
46
47
  results.requests_made += 1
47
48
  end
48
49
  else
49
- results.concat find_every.bind(self).call(options)
50
+ ShopifyAPI::Shop.current.throttle.run do
51
+ results.concat find_every.bind(self).call(options)
52
+ end
50
53
  results.requests_made += 1
51
54
  end
52
55
 
@@ -0,0 +1,75 @@
1
+ # this allows multiple concurrent workers to behave well, almost
2
+ # never triggering a 429, and distributing requests fairly evenly,
3
+ # rather than 1 worker hogging the bulk
4
+ # of requests until finished, which will typically happen with
5
+ # any naive, non-stochastic implementation.
6
+
7
+
8
+ module ShopifyAPI
9
+ class Shop
10
+ def throttle
11
+ @throttle ||= Throttle.new
12
+ end
13
+ end
14
+
15
+ class Throttle
16
+ attr_accessor :throttle, :throttle_increment, :requests_threshold
17
+ def initialize
18
+ @throttle = 0.6
19
+ @throttle_increment = @throttle
20
+ @requests_threshold = 10
21
+ end
22
+
23
+ def run(&block)
24
+ value = nil
25
+ retries ||= 0
26
+ begin
27
+ left = ShopifyAPI.credit_left
28
+ over = @requests_threshold - left
29
+ if over > 0
30
+ @throttle += (over * rand/20) + rand/10
31
+ sleep @throttle + rand/10
32
+ else
33
+ @throttle = (0.94 + rand/20) * @throttle
34
+ end
35
+ t = Time.now
36
+ value = yield
37
+ rescue ActiveResource::ClientError => e
38
+ case e.response.code
39
+ when '404'
40
+ logger.fatal "Shopify returned not found"
41
+ sleep 5 + retries + (rand * rand * 5)
42
+ retries += 1
43
+ if retries < 4
44
+ ActiveResource::Base.logger = Logger.new(STDOUT)
45
+ retry
46
+ else
47
+ ActiveResource::Base.logger = nil
48
+ raise
49
+ end
50
+ when '429'
51
+ logger.warn "Shopify hit api limit"
52
+ @throttle += rand/5
53
+ retries += 1
54
+ sleep (@throttle * 4 * retries) + rand/10
55
+ if retries < 10
56
+ retry
57
+ else
58
+ raise
59
+ end
60
+ else
61
+ raise
62
+ end
63
+ end
64
+ requests_made = left - ShopifyAPI.credit_left
65
+ if requests_made > 1
66
+ @throttle += (rand/20) * requests_made
67
+ sleep [0, (t + (requests_made * @throttle) - Time.now)].max + rand/10
68
+ else
69
+ @throttle = (0.94 + rand/20) * @throttle
70
+ sleep rand/20
71
+ end
72
+ value
73
+ end
74
+ end
75
+ end
@@ -1,3 +1,3 @@
1
1
  module ShopifyUnlimited
2
- VERSION = "0.0.13.threadsafe"
2
+ VERSION = "0.0.14.threadsafe"
3
3
  end
@@ -1,46 +1,3 @@
1
1
  require "shopify_unlimited/version"
2
2
  require 'shopify_unlimited/active_resource/base_extensions'
3
- require 'shopify_unlimited/active_resource/connection_extensions'
4
-
5
- module ShopifyUnlimited
6
- SHOPIFY_CREDIT_LIMIT_PERIOD = 5.minutes
7
-
8
- class << self
9
- attr_accessor :use_memcached
10
- def memcached
11
- return nil unless use_memcached
12
- @memcached ||= Dalli::Client.new()
13
- end
14
-
15
- def cache_key
16
- URI.parse(ShopifyAPI::Base.site.to_s).host + "_api_reset_time"
17
- end
18
-
19
- def cached_time(max)
20
- now = Time.now
21
- result = now
22
- return result unless memcached
23
- unless memcached.add(cache_key, now, 500)
24
- memcached.cas(cache_key, 500) do |cached_time|
25
- result = ((now - cached_time) > max) ? now : cached_time
26
- result
27
- end
28
- end
29
- result
30
- end
31
-
32
- def set_cached_time(time)
33
- return unless memcached
34
- memcached.set(cache_key, time, 500)
35
- end
36
-
37
-
38
- def estimated_time_until_reset
39
- credit_record = ShopifyAPI::Base.connection.shopify_credit
40
- time = credit_record.time unless credit_record.nil?
41
- time ||= cached_time(ShopifyUnlimited::SHOPIFY_CREDIT_LIMIT_PERIOD)
42
- est = ShopifyUnlimited::SHOPIFY_CREDIT_LIMIT_PERIOD - (Time.now - time)
43
- [est, 0].max
44
- end
45
- end
46
- end
3
+ require 'shopify_unlimited/shopify_api/throttle'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify_unlimited
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13.threadsafe
4
+ version: 0.0.14.threadsafe
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Johnston
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-01 00:00:00.000000000 Z
11
+ date: 2014-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activeresource
@@ -109,7 +109,7 @@ files:
109
109
  - Rakefile
110
110
  - lib/shopify_unlimited.rb
111
111
  - lib/shopify_unlimited/active_resource/base_extensions.rb
112
- - lib/shopify_unlimited/active_resource/connection_extensions.rb
112
+ - lib/shopify_unlimited/shopify_api/throttle.rb
113
113
  - lib/shopify_unlimited/version.rb
114
114
  - shopify_unlimited.gemspec
115
115
  - spec/spec_helper.rb
@@ -1,49 +0,0 @@
1
- module ::ShopifyUnlimited
2
-
3
- class CreditUsed
4
-
5
- attr_accessor :time, :used
6
- def initialize(used)
7
- @time = Time.now
8
- @used = used
9
- end
10
-
11
- def stale?(used)
12
- (@used > used) || ((Time.now - @time) > ShopifyUnlimited::SHOPIFY_CREDIT_LIMIT_PERIOD)
13
- end
14
-
15
- def estimated_time_until_reset
16
- est = ShopifyUnlimited::SHOPIFY_CREDIT_LIMIT_PERIOD - (Time.now - @time)
17
- [est, 0].max
18
- end
19
-
20
- end
21
- end
22
-
23
- module ::ActiveResource
24
- class Connection
25
- SHOPIFY_CREDIT_LIMIT_HEADER_PARAM = 'http_x_shopify_shop_api_call_limit'
26
-
27
- attr_reader :shopify_credit
28
- def handle_response_with_response_time_capture(response)
29
- handle_response_without_response_time_capture(response)
30
-
31
- if(shopify_credit_header = response[SHOPIFY_CREDIT_LIMIT_HEADER_PARAM])
32
- used = shopify_credit_header.split('/').shift.to_i
33
-
34
- if @shopify_credit.nil?
35
- cached_time = ::ShopifyUnlimited.cached_time(ShopifyUnlimited::SHOPIFY_CREDIT_LIMIT_PERIOD)
36
- @shopify_credit = ::ShopifyUnlimited::CreditUsed.new(used)
37
- @shopify_credit.time = cached_time
38
- elsif @shopify_credit.stale?(used)
39
- @shopify_credit = ::ShopifyUnlimited::CreditUsed.new(used)
40
- ::ShopifyUnlimited.set_cached_time(Time.now)
41
- else
42
- @shopify_credit.used = used
43
- end
44
- end
45
- response
46
- end
47
- alias_method_chain :handle_response, :response_time_capture
48
- end
49
- end