presto-client 0.5.12 → 0.5.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 080d9921005db52eff8e73d34436dd26a3b034bd
4
- data.tar.gz: 431dd1f2a7a1f3f199fd5fca9d80ba7a8135517b
3
+ metadata.gz: 25d825cdb3befbfa69b368f05d2267ed4bc3affd
4
+ data.tar.gz: abbc72ac27018abef03fbe2c5a122cc96aff68e1
5
5
  SHA512:
6
- metadata.gz: a509d1c1c269011e695d1bbda97f32b7f85203accfcc1986889059ac9130836704a2c26e21e86ab6381089a9fc6568752f22f62186560ce47920b4db2a536224
7
- data.tar.gz: 254363164f1df8e403c35b7bb17f17cdc63719b09a65495180accf5f493339742cc9a54ea662470b523096ae015b3ade3109d68cceff05c014682085dc8e1580
6
+ metadata.gz: f5988faa2e414bdb31a1368eb3a829e1a30872195a8bf6aa1a0ece60edb832ca64af70f6e3cfa8b2e85e7b20786b2ab943fdfa8b340158fab33d5d8279b8a440
7
+ data.tar.gz: 00eb3921405da85361bda22d588982e3e8d706ac118bd694cfab94849812bdb25e27ce8e5c0ba43d437d21a1fdbf03d9a09075722e4569082680ce5fa376c25e
data/ChangeLog CHANGED
@@ -1,3 +1,9 @@
1
+ 2018-12-10 version 0.5.13
2
+
3
+ * Added `query_timeout` and `plan_timeout` options with default disabled
4
+ * Changed timer to use CLOCK_MONOTONIC to avoid unexpected behavior when
5
+ system clock is updated
6
+
1
7
  2018-08-07 version 0.5.12
2
8
 
3
9
  * Upgrade to Presto 0.205 model
data/README.md CHANGED
@@ -94,12 +94,14 @@ $ bundle exec rake modelgen:latest
94
94
  * **time_zone** sets time zone of queries. Time zone affects some functions such as `format_datetime`.
95
95
  * **language** sets language of queries. Language affects some functions such as `format_datetime`.
96
96
  * **properties** set session properties. Session properties affect internal behavior such as `hive.force_local_scheduling: true`, `raptor.reader_stream_buffer_size: "32MB"`, etc.
97
+ * **query_timeout** sets timeout in seconds for the entire query execution (from the first API call until there're no more output data). If timeout happens, client raises PrestoQueryTimeoutError. Default is nil (disabled).
98
+ * **plan_timeout** sets timeout in seconds for query planning execution (from the first API call until result columns become available). If timeout happens, client raises PrestoQueryTimeoutError. Default is nil (disabled).
97
99
  * **http_headers** sets custom HTTP headers. It must be a Hash of string to string.
98
100
  * **http_proxy** sets host:port of a HTTP proxy server.
99
101
  * **http_debug** enables debug message to STDOUT for each HTTP requests.
100
102
  * **http_open_timeout** sets timeout in seconds to open new HTTP connection.
101
103
  * **http_timeout** sets timeout in seconds to read data from a server.
102
- * **model_version** set the presto version to which a job is submitted. Supported versions are 0.153 and 0.149. Default is 0.153.
104
+ * **model_version** set the presto version to which a job is submitted. Supported versions are 0.205, 0.178, 0.173, 0.153 and 0.149. Default is 0.205.
103
105
 
104
106
  See [RDoc](http://www.rubydoc.info/gems/presto-client/) for the full documentation.
105
107
 
@@ -112,4 +114,3 @@ See [RDoc](http://www.rubydoc.info/gems/presto-client/) for the full documentati
112
114
  3. git commit -am "vX.Y.Z"
113
115
  4. git tag "vX.Y.Z"
114
116
  5. git push --tags
115
-
@@ -40,4 +40,7 @@ module Presto::Client
40
40
 
41
41
  attr_reader :error_code, :error_name, :failure_info
42
42
  end
43
+
44
+ class PrestoQueryTimeoutError < PrestoError
45
+ end
43
46
  end
@@ -40,6 +40,15 @@ module Presto::Client
40
40
  @models = Models
41
41
  end
42
42
 
43
+ @plan_timeout = options[:plan_timeout]
44
+ @query_timeout = options[:query_timeout]
45
+
46
+ if @plan_timeout || @query_timeout
47
+ # this is set before the first call of faraday_get_with_retry so that
48
+ # resuming StatementClient with next_uri is also under timeout control.
49
+ @started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
50
+ end
51
+
43
52
  if next_uri
44
53
  response = faraday_get_with_retry(next_uri)
45
54
  @results = @models::QueryResults.decode(parse_body(response))
@@ -110,11 +119,13 @@ module Presto::Client
110
119
  if closed? || !has_next?
111
120
  return false
112
121
  end
113
- uri = @results.next_uri
114
122
 
123
+ uri = @results.next_uri
115
124
  response = faraday_get_with_retry(uri)
116
125
  @results = decode_model(uri, parse_body(response), @models::QueryResults)
117
126
 
127
+ raise_if_timeout!
128
+
118
129
  return true
119
130
  end
120
131
 
@@ -156,7 +167,7 @@ module Presto::Client
156
167
  private :parse_body
157
168
 
158
169
  def faraday_get_with_retry(uri, &block)
159
- start = Time.now
170
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
160
171
  attempts = 0
161
172
 
162
173
  begin
@@ -182,14 +193,46 @@ module Presto::Client
182
193
  end
183
194
  end
184
195
 
196
+ raise_if_timeout!
197
+
185
198
  attempts += 1
186
199
  sleep attempts * 0.1
187
- end while (Time.now - start) < @retry_timeout && !@closed
200
+ end while (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) < @retry_timeout && !@closed
188
201
 
189
202
  @exception = PrestoHttpError.new(408, "Presto API error due to timeout")
190
203
  raise @exception
191
204
  end
192
205
 
206
+ def raise_if_timeout!
207
+ if @started_at
208
+ if @results && @results.next_uri == nil
209
+ # query is already done
210
+ return
211
+ end
212
+
213
+ elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - @started_at
214
+
215
+ if @query_timeout && elapsed > @query_timeout
216
+ raise_timeout_error!
217
+ end
218
+
219
+ if @plan_timeout && (@results == nil || @results.columns == nil) &&
220
+ elapsed > @plan_timeout
221
+ # @results is not set (even first faraday_get_with_retry isn't called yet) or
222
+ # result from Presto doesn't include result schema. Query planning isn't done yet.
223
+ raise_timeout_error!
224
+ end
225
+ end
226
+ end
227
+
228
+ def raise_timeout_error!
229
+ if query_id = @results && @results.id
230
+ raise PrestoQueryTimeoutError, "Query #{query_id} timed out"
231
+ else
232
+ raise PrestoQueryTimeoutError, "Query timed out"
233
+ end
234
+ end
235
+
193
236
  def cancel_leaf_stage
194
237
  if uri = @results.next_uri
195
238
  response = @faraday.delete do |req|
@@ -15,6 +15,6 @@
15
15
  #
16
16
  module Presto
17
17
  module Client
18
- VERSION = "0.5.12"
18
+ VERSION = "0.5.13"
19
19
  end
20
20
  end
@@ -401,5 +401,160 @@ describe Presto::Client::StatementClient do
401
401
 
402
402
  StatementClient.new(faraday, query, options)
403
403
  end
404
+
405
+ describe "query timeout" do
406
+ let :headers do
407
+ {
408
+ "User-Agent" => "presto-ruby/#{VERSION}",
409
+ "X-Presto-Catalog" => options[:catalog],
410
+ "X-Presto-Schema" => options[:schema],
411
+ "X-Presto-User" => options[:user],
412
+ "X-Presto-Language" => options[:language],
413
+ "X-Presto-Time-Zone" => options[:time_zone],
414
+ }
415
+ end
416
+
417
+ let :planning_response do
418
+ {
419
+ id: "queryid",
420
+ nextUri: 'http://localhost/v1/next_uri',
421
+ stats: {},
422
+ }
423
+ end
424
+
425
+ let :early_running_response do
426
+ {
427
+ id: "queryid",
428
+ nextUri: 'http://localhost/v1/next_uri',
429
+ stats: {},
430
+ columns: [{name: "_col0", type: "bigint"}],
431
+ }
432
+ end
433
+
434
+ let :late_running_response do
435
+ {
436
+ id: "queryid",
437
+ nextUri: 'http://localhost/v1/next_uri',
438
+ stats: {},
439
+ columns: [{name: "_col0", type: "bigint"}],
440
+ data: "",
441
+ }
442
+ end
443
+
444
+ let :done_response do
445
+ {
446
+ id: "queryid",
447
+ stats: {},
448
+ columns: [{name: "_col0", type: "bigint"}],
449
+ }
450
+ end
451
+
452
+ before(:each) do
453
+ end
454
+
455
+ [:plan_timeout, :query_timeout].each do |timeout_type|
456
+ it "raises PrestoQueryTimeoutError if timeout during planning" do
457
+ stub_request(:post, "localhost/v1/statement").
458
+ with(body: query, headers: headers).
459
+ to_return(body: planning_response.to_json)
460
+
461
+ client = StatementClient.new(faraday, query, options.merge(timeout_type => 1))
462
+
463
+ stub_request(:get, "localhost/v1/next_uri").
464
+ with(headers: headers).
465
+ to_return(body: planning_response.to_json)
466
+ client.advance
467
+
468
+ sleep 1
469
+ stub_request(:get, "localhost/v1/next_uri").
470
+ with(headers: headers).
471
+ to_return(body: planning_response.to_json)
472
+ lambda do
473
+ client.advance
474
+ end.should raise_error(Presto::Client::PrestoQueryTimeoutError, "Query queryid timed out")
475
+ end
476
+
477
+ it "raises PrestoQueryTimeoutError if timeout during initial resuming" do
478
+ stub_request(:get, "localhost/v1/next_uri").
479
+ with(headers: headers).
480
+ to_return(body: lambda{|req| raise Timeout::Error.new("execution expired")})
481
+
482
+ lambda do
483
+ StatementClient.new(faraday, query, options.merge(timeout_type => 1), "/v1/next_uri")
484
+ end.should raise_error(Presto::Client::PrestoQueryTimeoutError, "Query timed out")
485
+ end
486
+
487
+ it "raises PrestoHttpError if timeout during initial resuming and #{timeout_type} < retry_timeout" do
488
+ stub_request(:get, "localhost/v1/next_uri").
489
+ with(headers: headers).
490
+ to_return(body: lambda{|req| raise Timeout::Error.new("execution expired")})
491
+
492
+ lambda do
493
+ StatementClient.new(faraday, query, options.merge(timeout_type => 2, retry_timeout: 1), "/v1/next_uri")
494
+ end.should raise_error(Presto::Client::PrestoHttpError, "Presto API error due to timeout")
495
+ end
496
+ end
497
+
498
+ it "doesn't raise errors with plan_timeout if query planning is done" do
499
+ stub_request(:post, "localhost/v1/statement").
500
+ with(body: query, headers: headers).
501
+ to_return(body: planning_response.to_json)
502
+
503
+ client = StatementClient.new(faraday, query, options.merge(plan_timeout: 1))
504
+
505
+ sleep 1
506
+
507
+ stub_request(:get, "localhost/v1/next_uri").
508
+ with(headers: headers).
509
+ to_return(body: early_running_response.to_json)
510
+ client.advance
511
+
512
+ stub_request(:get, "localhost/v1/next_uri").
513
+ with(headers: headers).
514
+ to_return(body: late_running_response.to_json)
515
+ client.advance
516
+ end
517
+
518
+ it "raises PrestoQueryTimeoutError if timeout during execution" do
519
+ stub_request(:post, "localhost/v1/statement").
520
+ with(body: query, headers: headers).
521
+ to_return(body: planning_response.to_json)
522
+
523
+ client = StatementClient.new(faraday, query, options.merge(query_timeout: 1))
524
+
525
+ stub_request(:get, "localhost/v1/next_uri").
526
+ with(headers: headers).
527
+ to_return(body: early_running_response.to_json)
528
+ client.advance
529
+
530
+ sleep 1
531
+ stub_request(:get, "localhost/v1/next_uri").
532
+ with(headers: headers).
533
+ to_return(body: late_running_response.to_json)
534
+ lambda do
535
+ client.advance
536
+ end.should raise_error(Presto::Client::PrestoQueryTimeoutError, "Query queryid timed out")
537
+ end
538
+
539
+ it "doesn't raise errors if query is done" do
540
+ stub_request(:post, "localhost/v1/statement").
541
+ with(body: query, headers: headers).
542
+ to_return(body: planning_response.to_json)
543
+
544
+ client = StatementClient.new(faraday, query, options.merge(query_timeout: 1))
545
+
546
+ stub_request(:get, "localhost/v1/next_uri").
547
+ with(headers: headers).
548
+ to_return(body: early_running_response.to_json)
549
+ client.advance
550
+
551
+ sleep 1
552
+ stub_request(:get, "localhost/v1/next_uri").
553
+ with(headers: headers).
554
+ to_return(body: done_response.to_json)
555
+ client.advance
556
+ end
557
+
558
+ end
404
559
  end
405
560
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: presto-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.12
4
+ version: 0.5.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-07 00:00:00.000000000 Z
11
+ date: 2018-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -170,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
170
170
  version: '0'
171
171
  requirements: []
172
172
  rubyforge_project:
173
- rubygems_version: 2.5.1
173
+ rubygems_version: 2.6.13
174
174
  signing_key:
175
175
  specification_version: 4
176
176
  summary: Presto client library