internetdata 2.0.1 → 2.1.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: 6341d4fee4674f684594cba1597efad23a7b83d36117a126bc46db283e562320
4
- data.tar.gz: c5e0c83a281b4ff2d51a45021cd9f5b31263c654c2197d8422ce728a3f062966
3
+ metadata.gz: 4c4799411a10284db486537f26bec70503a77692f56751121b34ec4bf89b2b22
4
+ data.tar.gz: db8745ef831d08fbfec78824c184acc194f1eb4bc62ba2e741f530ffff76fd40
5
5
  SHA512:
6
- metadata.gz: 778d2a234d36fb5c9e783fbfdb63df0b1f9bff7f069db19fb677957bd3d36d9ff46dd582a3bb28ab3fb43d31a150f76f538bc80a5cf4decb032e990393bf63ca
7
- data.tar.gz: e927fa802dfb5b852aa9a3612fe7de4c47ee0b3e7cbe7704c043bd4864c79f5e6aebb00c9e4bb01ef427b13384b7c7eeaa6b0f8581603e87070557f00c11682f
6
+ metadata.gz: 69292ca30d27411851f776f88a067176a14ef39331f5344dbd30ae345ca369357456b7bf353323f5c7e9f323f695600da02b9723e6a1e663806d36972f8e67a8
7
+ data.tar.gz: 9d5aa3458e1199c8ed121ecca2a1418dcab23c0725dac8a584f51ffa8ff13b0c1d4f7ac7b4d7a13408e5b928b25c3966a00d1f235ad768d113c3ef5513438762
data/README.md CHANGED
@@ -23,7 +23,7 @@ Requires Ruby 3.1 or newer.
23
23
 
24
24
  ## Usage
25
25
 
26
- Every database published today needs an API key carrying the `db.download` scope. Access is granted by contract, one family at a time, so there is no self-serve tier: write to [dev@internetdata.io](mailto:dev@internetdata.io) to be licensed and issued a key. `api_key:` is nevertheless optional - a client built without one sends no `Authorization` header at all, ready for a database served without a licence.
26
+ Every database published today needs an API key carrying the `db.download` scope. Access is granted by contract, one family at a time, so there is no self-serve tier: write to [dev@internetdata.io](mailto:dev@internetdata.io) to be licensed and issued a key. `api_key:` is nevertheless optional - a client built without one sends no `Authorization` header at all, ready for a database served without a license.
27
27
 
28
28
  ```ruby
29
29
  require 'internetdata'
@@ -92,6 +92,18 @@ client.database.downloads(limit: 20).each do |attempt|
92
92
  end
93
93
  ```
94
94
 
95
+ ### Timeouts
96
+
97
+ ```ruby
98
+ client = InternetData::Client.new(api_key: ENV['INTERNETDATA_API_KEY'], timeout: 10)
99
+
100
+ catalog = client.database.list(timeout: 5)
101
+ ```
102
+
103
+ `timeout` is in seconds and bounds each attempt, body included, so a call that is retried can take longer in total. It defaults to 30 seconds. The client's value is the default: from 2.1.0, `list`, `metadata`, `checksums`, `downloads` and `download_url` each take `timeout:` for that call alone.
104
+
105
+ `download` and `download_bytes` take no `timeout:` and raise `ArgumentError` if handed one, rather than accepting it and quietly doing nothing: a transfer runs to gigabytes and minutes, so any bound that suits a JSON call would abandon a healthy download. They bound only their connection with the client's value. `download_url` does take one, because minting the link is an ordinary API request - it bounds that request, not whatever you do with the link afterwards.
106
+
95
107
  ### Errors
96
108
 
97
109
  Failures raise an `InternetData::Error` carrying a `kind` and a `retryable?` flag:
@@ -12,7 +12,7 @@ module InternetData
12
12
  # Every database published today needs an API key carrying the `db.download`
13
13
  # scope, granted by contract one family at a time. The key is still OPTIONAL:
14
14
  # a client built without one sends no `Authorization` header at all, which is
15
- # what a database served without a licence would need.
15
+ # what a database served without a license would need.
16
16
  class Client
17
17
  # The licensed database downloads, and everything about them.
18
18
  attr_reader :database
@@ -5,6 +5,12 @@ module InternetData
5
5
  #
6
6
  # Not to be confused with {Database}, which is one entry in a {#list}, nor with
7
7
  # the generated {DatabaseV2Api} underneath, which speaks the wire.
8
+ #
9
+ # Every JSON call here takes `timeout:`, in seconds, bounding each ATTEMPT of
10
+ # that call alone and overriding the bound the client was built with. The two
11
+ # transfers take none, and are refused it rather than ignoring it: a database
12
+ # runs to gigabytes and minutes, so a bound that suits a JSON call would
13
+ # abandon a healthy download.
8
14
  class DatabaseApi
9
15
  def initialize(transport, retries:)
10
16
  @transport = transport
@@ -25,8 +31,10 @@ module InternetData
25
31
  # server decides that per key. So the catalog is not the same for every key,
26
32
  # a listing fetched with one key says nothing about another, and there is no
27
33
  # other source to reconstruct it from.
28
- def list
29
- call { @api.list_databases.databases }
34
+ #
35
+ # @param timeout [Numeric, nil] seconds this attempt may take, for THIS call only.
36
+ def list(timeout: nil)
37
+ call { @api.list_databases(timeout: timeout).databases }
30
38
  end
31
39
 
32
40
  # What is inside one database: schema, sample rows, row count and sizes.
@@ -34,8 +42,10 @@ module InternetData
34
42
  # `updated` and `entries` answer whether today's build is worth fetching, and
35
43
  # `size` is bytes per format, which is what a transfer should be budgeted
36
44
  # against before it starts.
37
- def metadata(id)
38
- call { @api.database_metadata_v2(id) }
45
+ #
46
+ # @param timeout [Numeric, nil] seconds this attempt may take, for THIS call only.
47
+ def metadata(id, timeout: nil)
48
+ call { @api.database_metadata_v2(id, timeout: timeout) }
39
49
  end
40
50
 
41
51
  # The digests for one published file.
@@ -43,15 +53,19 @@ module InternetData
43
53
  # Returns the whole set rather than one algorithm: which digests a database
44
54
  # publishes is the API's choice, not ours, and the response nests them one
45
55
  # level down under `checksums`.
46
- def checksums(id, format)
56
+ #
57
+ # @param timeout [Numeric, nil] seconds this attempt may take, for THIS call only.
58
+ def checksums(id, format, timeout: nil)
47
59
  check_format!(format)
48
- call { @api.database_checksum_v2(id, format).checksums }
60
+ call { @api.database_checksum_v2(id, format, timeout: timeout).checksums }
49
61
  end
50
62
 
51
63
  # Your organization's recent download attempts, newest first, refusals
52
64
  # included.
53
- def downloads(limit: nil)
54
- call { @api.list_downloads(limit.nil? ? {} : { limit: limit }).downloads }
65
+ #
66
+ # @param timeout [Numeric, nil] seconds this attempt may take, for THIS call only.
67
+ def downloads(limit: nil, timeout: nil)
68
+ call { @api.list_downloads(limit: limit, timeout: timeout).downloads }
55
69
  end
56
70
 
57
71
  # The time-limited URL for one database file.
@@ -61,9 +75,13 @@ module InternetData
61
75
  # caller decides how to transfer a file that routinely runs to gigabytes; the
62
76
  # link authorizes the START of a transfer, so one already running is not
63
77
  # interrupted when it lapses.
64
- def download_url(id, format)
78
+ #
79
+ # @param timeout [Numeric, nil] seconds this attempt may take, for THIS call
80
+ # only. It bounds the request that MINTS the link, which is an ordinary
81
+ # JSON call, and says nothing about the transfer you then run with it.
82
+ def download_url(id, format, timeout: nil)
65
83
  check_format!(format)
66
- call { redirect_location(id, format) }
84
+ call { redirect_location(id, format, timeout) }
67
85
  end
68
86
 
69
87
  # Download one database file to `path`, and return the bytes written.
@@ -177,8 +195,8 @@ module InternetData
177
195
  "invalid value for \"format\", must be one of #{DatabaseFormat.all_vars}"
178
196
  end
179
197
 
180
- def redirect_location(id, format)
181
- @api.download_database_v2(id, format)
198
+ def redirect_location(id, format, timeout)
199
+ @api.download_database_v2(id, format, timeout: timeout)
182
200
  raise Error.new(:server_error, 'expected a redirect to object storage')
183
201
  rescue ApiError => e
184
202
  raise unless e.code == 302
@@ -50,9 +50,15 @@ module InternetData
50
50
  # is true for every value it can be given, so the download's 302 would be
51
51
  # chased and a multi-gigabyte database read into memory. Nothing this API
52
52
  # serves is meant to be followed.
53
+ #
54
+ # `opts[:timeout]` is a per-call override of the configured bound, which the
55
+ # generated client would otherwise apply to every request it builds. It
56
+ # reaches here as an ordinary generated `opts` entry, so one seam bounds
57
+ # every call whether the request was built by hand or by the generator.
53
58
  def build_request(http_method, path, opts = {})
54
59
  request = super
55
60
  request.options[:followlocation] = false
61
+ request.options[:timeout] = opts[:timeout] unless opts[:timeout].nil?
56
62
  request
57
63
  end
58
64
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module InternetData
4
- VERSION = '2.0.1'
4
+ VERSION = '2.1.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: internetdata
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mslm Dev