Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ $ bundle exec rake modelgen:latest
* **http_timeout** sets timeout in seconds to read data from a server.
* **gzip** enables gzip compression.
* **follow_redirect** enables HTTP redirection support.
* **faraday_adapter** sets the Faraday adapter to use. Default is `Faraday.default_adapter`. To reuse persistent HTTP connections, install `faraday-net_http_persistent` and specify `:net_http_persistent`.
* **model_version** set the Trino version to which a job is submitted. Supported versions are 351, 316, 303, 0.205, 0.178, 0.173, 0.153 and 0.149. Default is 351.

See [RDoc](http://www.rubydoc.info/gems/presto-client/) for the full documentation.
Expand Down
9 changes: 5 additions & 4 deletions lib/trino/client/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ module Trino::Client
class Client
def initialize(options)
@options = options
@faraday = Trino::Client.faraday_client(options)
end

def query(query, &block)
q = Query.start(query, @options)
q = Query.start(query, @faraday, @options)
if block
begin
yield q
Expand All @@ -37,15 +38,15 @@ def query(query, &block)
end

def resume_query(next_uri)
return Query.resume(next_uri, @options)
return Query.resume(next_uri, @faraday, @options)
end

def kill(query_id)
return Query.kill(query_id, @options)
return Query.kill(query_id, @faraday, @options)
end

def run(query)
q = Query.start(query, @options)
q = Query.start(query, @faraday, @options)
begin
columns = q.columns
if columns.empty?
Expand Down
50 changes: 24 additions & 26 deletions lib/trino/client/faraday_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@
# limitations under the License.
#
module Trino::Client
FARADAY1_USED = Faraday::VERSION.start_with?("1.")
private_constant :FARADAY1_USED

require 'base64'
require 'cgi'

module TrinoHeaders
Expand Down Expand Up @@ -77,26 +76,17 @@ def self.faraday_client(options)
faraday_options[:ssl] = ssl if ssl

faraday = Faraday.new(faraday_options) do |faraday|
if options[:user] && options[:password]
# https://lostisland.github.io/faraday/middleware/authentication
if FARADAY1_USED
faraday.request(:basic_auth, options[:user], options[:password])
else
faraday.request :authorization, :basic, options[:user], options[:password]
end
end
if options[:follow_redirect]
faraday.response :follow_redirects
end
if options[:gzip]
faraday.request :gzip
end
faraday.response :logger, options[:http_debug_logger] if options[:http_debug]
faraday.adapter Faraday.default_adapter
faraday.adapter(options[:faraday_adapter] || Faraday.default_adapter)
end

faraday.headers.merge!(HEADERS)
faraday.headers.merge!(optional_headers(options))

return faraday
end
Expand Down Expand Up @@ -129,71 +119,79 @@ def self.faraday_ssl_options(options)
return ssl
end

def self.optional_headers(options)
usePrestoHeader = false
if options[:model_version] && options[:model_version] < 351
usePrestoHeader = true
def self.build_query_headers(options)
use_presto_headers = false
if options[:model_version] && options[:model_version].to_i < 351
use_presto_headers = true
end

headers = {}

if options[:user] && options[:password]
credentials = Base64.strict_encode64(
"#{options[:user]}:#{options[:password]}"
)
headers["Authorization"] = "Basic #{credentials}"
end

if v = options[:user]
if usePrestoHeader
if use_presto_headers
headers[PrestoHeaders::PRESTO_USER] = v
else
headers[TrinoHeaders::TRINO_USER] = v
end
end
if v = options[:source]
if usePrestoHeader
if use_presto_headers
headers[PrestoHeaders::PRESTO_SOURCE] = v
else
headers[TrinoHeaders::TRINO_SOURCE] = v
end
end
if v = options[:catalog]
if usePrestoHeader
if use_presto_headers
headers[PrestoHeaders::PRESTO_CATALOG] = v
else
headers[TrinoHeaders::TRINO_CATALOG] = v
end
end
if v = options[:schema]
if usePrestoHeader
if use_presto_headers
headers[PrestoHeaders::PRESTO_SCHEMA] = v
else
headers[TrinoHeaders::TRINO_SCHEMA] = v
end
end
if v = options[:time_zone]
if usePrestoHeader
if use_presto_headers
headers[PrestoHeaders::PRESTO_TIME_ZONE] = v
else
headers[TrinoHeaders::TRINO_TIME_ZONE] = v
end
end
if v = options[:language]
if usePrestoHeader
if use_presto_headers
headers[PrestoHeaders::PRESTO_LANGUAGE] = v
else
headers[TrinoHeaders::TRINO_LANGUAGE] = v
end
end
if v = options[:properties]
if usePrestoHeader
if use_presto_headers
headers[PrestoHeaders::PRESTO_SESSION] = encode_properties(v)
else
headers[TrinoHeaders::TRINO_SESSION] = encode_properties(v)
end
end
if v = options[:client_info]
if usePrestoHeader
if use_presto_headers
headers[PrestoHeaders::PRESTO_CLIENT_INFO] = encode_client_info(v)
else
headers[TrinoHeaders::TRINO_CLIENT_INFO] = encode_client_info(v)
end
end
if v = options[:client_tags]
if usePrestoHeader
if use_presto_headers
headers[PrestoHeaders::PRESTO_CLIENT_TAGS] = encode_client_tags(v)
else
headers[TrinoHeaders::TRINO_CLIENT_TAGS] = encode_client_tags(v)
Expand Down Expand Up @@ -245,6 +243,6 @@ def self.encode_client_tags(tags)
Array(tags).join(",")
end

private_class_method :faraday_ssl_options, :optional_headers, :encode_properties, :encode_client_info, :encode_client_tags
private_class_method :faraday_ssl_options, :encode_properties, :encode_client_info, :encode_client_tags

end
18 changes: 8 additions & 10 deletions lib/trino/client/query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,24 @@ module Trino::Client
require 'trino/client/statement_client'

class Query
def self.start(query, options)
new StatementClient.new(faraday_client(options), query, options)
def self.start(query, faraday, options)
new StatementClient.new(faraday, query, options)
end

def self.resume(next_uri, options)
new StatementClient.new(faraday_client(options), nil, options, next_uri)
def self.resume(next_uri, faraday, options)
new StatementClient.new(faraday, nil, options, next_uri)
end

def self.kill(query_id, options)
faraday = faraday_client(options)
def self.kill(query_id, faraday, options)
response = faraday.delete do |req|
req.headers.merge!(
Trino::Client.build_query_headers(options)
)
req.url "/v1/query/#{query_id}"
end
return response.status / 100 == 2
end

def self.faraday_client(options)
Trino::Client.faraday_client(options)
end

def self.transform_row(column_value_parsers, row)
row_object = {}

Expand Down
8 changes: 7 additions & 1 deletion lib/trino/client/statement_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class StatementClient

def initialize(faraday, query, options, next_uri=nil)
@faraday = faraday
@headers = Trino::Client.build_query_headers(options)

@options = options
@query = query
Expand Down Expand Up @@ -72,6 +73,7 @@ def post_query_request!
begin
r = @faraday.post do |req|
req.url uri
req.headers.merge!(@headers)

req.body = @query
init_request(req)
Expand Down Expand Up @@ -229,7 +231,9 @@ def with_retry_loop
def faraday_get_with_retry(uri)
with_retry_loop do
begin
response = @faraday.get(uri)
response = @faraday.get(uri) do |req|
req.headers.merge!(@headers)
end
rescue Faraday::TimeoutError, Faraday::ConnectionFailed
throw :retry_with_backoff
rescue => e
Expand Down Expand Up @@ -278,6 +282,7 @@ def raise_timeout_error!
def cancel_leaf_stage
if uri = @results.partial_cancel_uri
@faraday.delete do |req|
req.headers.merge!(@headers)
req.url uri
end
end
Expand All @@ -291,6 +296,7 @@ def close
begin
if uri = @results.next_uri
@faraday.delete do |req|
req.headers.merge!(@headers)
req.url uri
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/basic_query_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@

it 'current query result' do
@client.query('show schemas') do |q|
expect(q.current_results.info_uri).to start_with('http://localhost:8080/ui/query.html')
expect(q.current_results.info_uri).to start_with('http://localhost:8080/ui')
end
end

Expand Down
123 changes: 122 additions & 1 deletion spec/client_spec.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,128 @@
require 'spec_helper'

describe Trino::Client::Client do
let(:client) { Trino::Client.new({}) }
let(:client) do
Trino::Client.new(server: "localhost:8080")
end

describe "Faraday client reuse" do
let(:options) do
{
server: "localhost:8080",
user: "test-user"
}
end

let(:faraday) do
instance_double(Faraday::Connection)
end

before do
allow(Trino::Client)
.to receive(:faraday_client)
.with(options)
.and_return(faraday)
end

it "creates one Faraday client per Client instance" do
expect(Trino::Client)
.to receive(:faraday_client)
.with(options)
.once
.and_return(faraday)

described_class.new(options)
end

it "reuses the same Faraday client for multiple queries" do
client = described_class.new(options)
first_query = instance_double(Trino::Client::Query)
second_query = instance_double(Trino::Client::Query)

expect(Trino::Client::Query)
.to receive(:start)
.with("select 1", faraday, options)
.and_return(first_query)

expect(Trino::Client::Query)
.to receive(:start)
.with("select 2", faraday, options)
.and_return(second_query)

expect(client.query("select 1")).to eq(first_query)
expect(client.query("select 2")).to eq(second_query)
end

it "reuses the same Faraday client when running a query" do
client = described_class.new(options)
query = instance_double(
Trino::Client::Query,
columns: [],
close: nil
)

expect(Trino::Client::Query)
.to receive(:start)
.with("select 1", faraday, options)
.and_return(query)

expect(client.run("select 1")).to eq([[], []])
end

it "reuses the same Faraday client when resuming a query" do
client = described_class.new(options)
query = instance_double(Trino::Client::Query)
next_uri = "http://localhost:8080/v1/statement/next"

expect(Trino::Client::Query)
.to receive(:resume)
.with(next_uri, faraday, options)
.and_return(query)

expect(client.resume_query(next_uri)).to eq(query)
end

it "reuses the same Faraday client when killing a query" do
client = described_class.new(options)

expect(Trino::Client::Query)
.to receive(:kill)
.with("query-id", faraday, options)
.and_return(true)

expect(client.kill("query-id")).to eq(true)
end

it "creates a separate Faraday client for each Client instance" do
first_faraday = instance_double(Faraday::Connection)
second_faraday = instance_double(Faraday::Connection)

expect(Trino::Client)
.to receive(:faraday_client)
.with(options)
.twice
.and_return(first_faraday, second_faraday)

first_client = described_class.new(options)
second_client = described_class.new(options)

first_query = instance_double(Trino::Client::Query)
second_query = instance_double(Trino::Client::Query)

expect(Trino::Client::Query)
.to receive(:start)
.with("select 1", first_faraday, options)
.and_return(first_query)

expect(Trino::Client::Query)
.to receive(:start)
.with("select 2", second_faraday, options)
.and_return(second_query)

first_client.query("select 1")
second_client.query("select 2")
end
end

describe 'rehashes' do
let(:columns) do
Expand Down
Loading
Loading