easyship 0.2.0 → 0.3.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 +4 -4
- data/CHANGELOG.md +7 -1
- data/README.md +43 -2
- data/lib/easyship/configuration.rb +3 -1
- data/lib/easyship/pagination/cursor.rb +21 -2
- data/lib/easyship/rate_limiting/rate_limiter.rb +12 -0
- data/lib/easyship/rate_limiting/window_rate_limiter.rb +50 -0
- data/lib/easyship/version.rb +1 -1
- data/lib/easyship.rb +2 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0e185adc98f576e3cf15ffc1ca38edf2dca8a0ffa580f68a731c900c3632392b
|
|
4
|
+
data.tar.gz: e15d52b3f530c58883fb8f50b086db537939ceed2fc1afff3579ea6aa82373c1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 707860b193dbc25e916f8d0e5e68a2a3c8e34498e523871e243cf487f1e5c4c2469ed274099899b1b50c22598dc085906eca132f9e537515c43bf03428040c02
|
|
7
|
+
data.tar.gz: ec38670ff9d6626bc62485d8c836d00c1efb8e4a8218214c5c6b36b01570ad3b71906511c2459dc4a74b3a5ed91e3d3f91bd5f07586e75d481dc2ebf142a4d9a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
-
## [
|
|
3
|
+
## [v0.3.0](https://github.com/mmarusyk/easyship/tree/v0.3.0) - 2025-11-29
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Rate limiting for cursor by @mmarusyk in https://github.com/mmarusyk/easyship/pull/13
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## [v0.2.0](https://github.com/mmarusyk/easyship/tree/v0.2.0) - 2025-05-04
|
|
4
10
|
|
|
5
11
|
### Added
|
|
6
12
|
- Add response_body and response_header to Easyship::Error
|
data/README.md
CHANGED
|
@@ -58,7 +58,7 @@ Easyship.configure do |config|
|
|
|
58
58
|
end
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
Configuration supports the next keys: `url`, `api_key`, `per_page`.
|
|
61
|
+
Configuration supports the next keys: `url`, `api_key`, `per_page`, `requests_per_second`, `requests_per_minute`.
|
|
62
62
|
|
|
63
63
|
### Making Requests
|
|
64
64
|
`Easyship::Client` supports the next methods: `get`, `post`, `put`, `delete`.
|
|
@@ -131,7 +131,48 @@ end
|
|
|
131
131
|
shipments # Returns all shipments from all pages
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
-
To setup items
|
|
134
|
+
To setup items per page, use the key `per_page` in your configuration.
|
|
135
|
+
|
|
136
|
+
For Example:
|
|
137
|
+
|
|
138
|
+
```ruby
|
|
139
|
+
# Global defaults
|
|
140
|
+
Easyship.configure do |config|
|
|
141
|
+
config.per_page = 100
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Per-call overrides (any of these are supported)
|
|
145
|
+
shipments = []
|
|
146
|
+
Easyship::Client.instance.get('/2023-01/shipments', {
|
|
147
|
+
per_page: 50,
|
|
148
|
+
}) do |page|
|
|
149
|
+
shipments.concat(page[:shipments])
|
|
150
|
+
end
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Rate limiting during pagination:
|
|
154
|
+
- The cursor has no default rate limiting; it uses nil to indicate that rate limiting is disabled.
|
|
155
|
+
- Use [Rate limiting documentation](https://developers.easyship.com/reference/rate-limit) for more details which values to set.
|
|
156
|
+
- You can override the limits per call, by passing `requests_per_second` and `requests_per_minute`.
|
|
157
|
+
|
|
158
|
+
Examples:
|
|
159
|
+
|
|
160
|
+
```ruby
|
|
161
|
+
# Global defaults
|
|
162
|
+
Easyship.configure do |config|
|
|
163
|
+
config.requests_per_second = 10
|
|
164
|
+
config.requests_per_minute = 60
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Per-call overrides (any of these are supported)
|
|
168
|
+
shipments = []
|
|
169
|
+
Easyship::Client.instance.get('/2023-01/shipments', {
|
|
170
|
+
requests_per_second: 5,
|
|
171
|
+
requests_per_minute: 40,
|
|
172
|
+
}) do |page|
|
|
173
|
+
shipments.concat(page[:shipments])
|
|
174
|
+
end
|
|
175
|
+
```
|
|
135
176
|
|
|
136
177
|
## Development
|
|
137
178
|
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
module Easyship
|
|
4
4
|
# Represents the configuration settings for the Easyship client.
|
|
5
5
|
class Configuration
|
|
6
|
-
attr_accessor :url, :api_key, :per_page
|
|
6
|
+
attr_accessor :url, :api_key, :per_page, :requests_per_second, :requests_per_minute
|
|
7
7
|
|
|
8
8
|
def initialize
|
|
9
9
|
@url = nil
|
|
10
10
|
@api_key = nil
|
|
11
11
|
@per_page = 100 # Maximum possible number of items per page
|
|
12
|
+
@requests_per_second = nil
|
|
13
|
+
@requests_per_minute = nil
|
|
12
14
|
end
|
|
13
15
|
end
|
|
14
16
|
end
|
|
@@ -4,20 +4,26 @@ module Easyship
|
|
|
4
4
|
module Pagination
|
|
5
5
|
# Represents a pagination object
|
|
6
6
|
class Cursor
|
|
7
|
-
|
|
7
|
+
CONFIGURATION_VARIABLES = %i[requests_per_second requests_per_minute].freeze
|
|
8
|
+
|
|
9
|
+
attr_reader :client, :path, :params, :key, :per_page, :requests_per_second, :requests_per_minute
|
|
8
10
|
|
|
9
11
|
def initialize(client, path, params)
|
|
10
12
|
@client = client
|
|
11
13
|
@path = path
|
|
12
14
|
@params = params
|
|
13
15
|
@per_page = params[:per_page] || Easyship.configuration.per_page
|
|
16
|
+
@requests_per_second = params[:requests_per_second] || Easyship.configuration.requests_per_second
|
|
17
|
+
@requests_per_minute = params[:requests_per_minute] || Easyship.configuration.requests_per_minute
|
|
14
18
|
end
|
|
15
19
|
|
|
16
20
|
def all
|
|
17
21
|
page = 1
|
|
18
22
|
|
|
19
23
|
loop do
|
|
20
|
-
|
|
24
|
+
limiter.throttle!
|
|
25
|
+
|
|
26
|
+
body = client.get(path, build_request_params(page: page))
|
|
21
27
|
|
|
22
28
|
break if body.nil? || body.empty?
|
|
23
29
|
|
|
@@ -28,6 +34,19 @@ module Easyship
|
|
|
28
34
|
page += 1
|
|
29
35
|
end
|
|
30
36
|
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def build_request_params(page:)
|
|
41
|
+
params.merge(page: page, per_page: per_page).except(*CONFIGURATION_VARIABLES)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def limiter
|
|
45
|
+
@limiter ||= Easyship::RateLimiting::WindowRateLimiter.new(
|
|
46
|
+
requests_per_second: requests_per_second,
|
|
47
|
+
requests_per_minute: requests_per_minute
|
|
48
|
+
)
|
|
49
|
+
end
|
|
31
50
|
end
|
|
32
51
|
end
|
|
33
52
|
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Easyship
|
|
4
|
+
module RateLimiting
|
|
5
|
+
# Represents WindowRateLimiter
|
|
6
|
+
class WindowRateLimiter < RateLimiter
|
|
7
|
+
attr_reader :timestamps, :requests_per_second, :requests_per_minute
|
|
8
|
+
|
|
9
|
+
def initialize(requests_per_second:, requests_per_minute:)
|
|
10
|
+
super()
|
|
11
|
+
@requests_per_second = requests_per_second
|
|
12
|
+
@requests_per_minute = requests_per_minute
|
|
13
|
+
@timestamps = []
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def throttle!
|
|
17
|
+
now = Time.now
|
|
18
|
+
|
|
19
|
+
timestamps << now
|
|
20
|
+
|
|
21
|
+
# Remove timestamps older than a minute
|
|
22
|
+
timestamps.reject! { |t| t < now - 60 }
|
|
23
|
+
|
|
24
|
+
check_second_window(now)
|
|
25
|
+
check_minute_window(now)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def check_second_window(now)
|
|
31
|
+
second_requests = timestamps.count { |t| t > now - 1 }
|
|
32
|
+
|
|
33
|
+
return if !requests_per_second || second_requests < requests_per_second
|
|
34
|
+
|
|
35
|
+
first_in_seconds = timestamps.find { |t| t > now - 1 }
|
|
36
|
+
sleep_time = (first_in_seconds + 1) - now
|
|
37
|
+
|
|
38
|
+
sleep(sleep_time) if sleep_time.positive?
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def check_minute_window(now)
|
|
42
|
+
return if !requests_per_minute || timestamps.size < requests_per_minute
|
|
43
|
+
|
|
44
|
+
sleep_time = (timestamps.first + 60) - now
|
|
45
|
+
|
|
46
|
+
sleep(sleep_time) if sleep_time.positive?
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
data/lib/easyship/version.rb
CHANGED
data/lib/easyship.rb
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
require_relative 'easyship/version'
|
|
4
4
|
require_relative 'easyship/configuration'
|
|
5
5
|
require_relative 'easyship/client'
|
|
6
|
+
require_relative 'easyship/rate_limiting/rate_limiter'
|
|
7
|
+
require_relative 'easyship/rate_limiting/window_rate_limiter'
|
|
6
8
|
|
|
7
9
|
# Provides configuration options for the Easyship gem.
|
|
8
10
|
module Easyship
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: easyship
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michael Marusyk
|
|
@@ -56,6 +56,8 @@ files:
|
|
|
56
56
|
- lib/easyship/handlers/response_body_handler.rb
|
|
57
57
|
- lib/easyship/middleware/error_handler_middleware.rb
|
|
58
58
|
- lib/easyship/pagination/cursor.rb
|
|
59
|
+
- lib/easyship/rate_limiting/rate_limiter.rb
|
|
60
|
+
- lib/easyship/rate_limiting/window_rate_limiter.rb
|
|
59
61
|
- lib/easyship/version.rb
|
|
60
62
|
- sig/easyship.rbs
|
|
61
63
|
homepage: https://rubygems.org/gems/easyship
|
|
@@ -81,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
81
83
|
- !ruby/object:Gem::Version
|
|
82
84
|
version: '0'
|
|
83
85
|
requirements: []
|
|
84
|
-
rubygems_version: 3.6.
|
|
86
|
+
rubygems_version: 3.6.9
|
|
85
87
|
specification_version: 4
|
|
86
88
|
summary: A Ruby client for integrating with Easyship's API for shipping and logistics
|
|
87
89
|
management.
|