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
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ accurate and fully typed.
- [Advanced Usage](#advanced-usage)
- [Additional Options](#additional-options)
- [Setting the endpoint](#setting-the-endpoint)
- [Setting the request timeout](#setting-the-request-timeout)
- [Configuring the Faraday Client](#configuring-the-faraday-client)
- [Using the Faraday Client](#using-the-faraday-client)
- [Overriding the Client](#overriding-the-client)
Expand Down Expand Up @@ -381,6 +382,7 @@ the constructor takes some advanced options that affect behavior.
seam = Seam.new(
api_key: "your-api-key",
endpoint: "https://example.com",
timeout: 30,
faraday_options: {},
faraday_retry_options: {}
)
Expand All @@ -392,6 +394,7 @@ these options may be passed in as keyword arguments.
```ruby
seam = Seam.from_api_key("some-api-key",
endpoint: "https://example.com",
timeout: 30,
faraday_options: {},
faraday_retry_options: {})
```
Expand All @@ -403,6 +406,27 @@ e.g., testing or proxy setups. This option corresponds to the [Faraday](https://

Either pass the `endpoint` option, or set the `SEAM_ENDPOINT` environment variable.

#### Setting the request timeout

Requests time out after 30 seconds by default.
Pass the `timeout` option, in seconds, to override this:

```ruby
seam = Seam.new(api_key: "your-api-key", timeout: 60)
```

The value sets both the Faraday `timeout` and `open_timeout`.
Either may be set independently via `faraday_options`, which takes precedence:

```ruby
seam = Seam.new(
api_key: "your-api-key",
faraday_options: {request: {timeout: 60, open_timeout: 5}}
)
```

A request that exceeds the timeout raises `Faraday::TimeoutError`.

#### Configuring the Faraday Client

The Faraday client and retry behavior may be configured with custom initiation options
Expand Down
9 changes: 5 additions & 4 deletions lib/seam.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ def self.new(**args)
Seam::Http.new(**args)
end

def self.from_api_key(api_key, endpoint: nil, wait_for_action_attempt: true)
Seam::Http.from_api_key(api_key, endpoint: endpoint, wait_for_action_attempt: wait_for_action_attempt)
def self.from_api_key(api_key, endpoint: nil, wait_for_action_attempt: true, timeout: nil)
Seam::Http.from_api_key(api_key, endpoint: endpoint, wait_for_action_attempt: wait_for_action_attempt,
timeout: timeout)
end

def self.from_personal_access_token(personal_access_token, workspace_id, endpoint: nil, wait_for_action_attempt: true)
Seam::Http.from_personal_access_token(personal_access_token, workspace_id, endpoint: endpoint, wait_for_action_attempt: wait_for_action_attempt)
def self.from_personal_access_token(personal_access_token, workspace_id, endpoint: nil, wait_for_action_attempt: true, timeout: nil)
Seam::Http.from_personal_access_token(personal_access_token, workspace_id, endpoint: endpoint, wait_for_action_attempt: wait_for_action_attempt, timeout: timeout)
end

def self.lts_version
Expand Down
2 changes: 2 additions & 0 deletions lib/seam/default_endpoint.rb → lib/seam/defaults.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@

module Seam
DEFAULT_ENDPOINT = "https://connect.getseam.com"

DEFAULT_TIMEOUT = 30
end
9 changes: 5 additions & 4 deletions lib/seam/http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ def self.new(**args)
Http::SingleWorkspace.new(**args)
end

def self.from_api_key(api_key, endpoint: nil, wait_for_action_attempt: true)
Http::SingleWorkspace.from_api_key(api_key, endpoint: endpoint, wait_for_action_attempt: wait_for_action_attempt)
def self.from_api_key(api_key, endpoint: nil, wait_for_action_attempt: true, timeout: nil)
Http::SingleWorkspace.from_api_key(api_key, endpoint: endpoint, wait_for_action_attempt: wait_for_action_attempt,
timeout: timeout)
end

def self.from_personal_access_token(personal_access_token, workspace_id, endpoint: nil, wait_for_action_attempt: true)
def self.from_personal_access_token(personal_access_token, workspace_id, endpoint: nil, wait_for_action_attempt: true, timeout: nil)
Http::SingleWorkspace.from_personal_access_token(personal_access_token, workspace_id, endpoint: endpoint,
wait_for_action_attempt: wait_for_action_attempt)
wait_for_action_attempt: wait_for_action_attempt, timeout: timeout)
end

class ApiError < StandardError
Expand Down
9 changes: 5 additions & 4 deletions lib/seam/http_multi_workspace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ module Http
class MultiWorkspace
attr_reader :client, :defaults

def initialize(personal_access_token:, endpoint: nil, wait_for_action_attempt: true, faraday_options: {},
faraday_retry_options: {})
def initialize(personal_access_token:, endpoint: nil, wait_for_action_attempt: true, timeout: nil,
faraday_options: {}, faraday_retry_options: {})
@wait_for_action_attempt = wait_for_action_attempt
@defaults = {"wait_for_action_attempt" => wait_for_action_attempt}
@endpoint = Http::Options.get_endpoint(endpoint)
@auth_headers = Http::Auth.get_auth_headers_for_multi_workspace_personal_access_token(personal_access_token)
@client = Http::Request.create_faraday_client(@endpoint, @auth_headers, faraday_options,
faraday_retry_options)
faraday_retry_options, timeout: timeout)
end

def self.lts_version
Expand All @@ -36,11 +36,12 @@ def workspaces
@workspaces ||= WorkspacesProxy.new(Seam::Clients::Workspaces.new(client: @client, defaults: @defaults))
end

def self.from_personal_access_token(personal_access_token, endpoint: nil, wait_for_action_attempt: true, faraday_options: {}, faraday_retry_options: {})
def self.from_personal_access_token(personal_access_token, endpoint: nil, wait_for_action_attempt: true, timeout: nil, faraday_options: {}, faraday_retry_options: {})
new(
personal_access_token: personal_access_token,
endpoint: endpoint,
wait_for_action_attempt: wait_for_action_attempt,
timeout: timeout,
faraday_options: faraday_options,
faraday_retry_options: faraday_retry_options
)
Expand Down
13 changes: 7 additions & 6 deletions lib/seam/http_single_workspace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class SingleWorkspace
attr_reader :client, :defaults

def initialize(client: nil, api_key: nil, personal_access_token: nil, workspace_id: nil, endpoint: nil,
wait_for_action_attempt: true, faraday_options: {}, faraday_retry_options: {})
wait_for_action_attempt: true, timeout: nil, faraday_options: {}, faraday_retry_options: {})
@defaults = Seam::DeepHashAccessor.new({"wait_for_action_attempt" => wait_for_action_attempt})

# A client carries its own endpoint and authorization, so the auth
Expand All @@ -28,7 +28,8 @@ def initialize(client: nil, api_key: nil, personal_access_token: nil, workspace_
@endpoint = options[:endpoint]
@auth_headers = options[:auth_headers]

Http::Request.create_faraday_client(@endpoint, @auth_headers, faraday_options, faraday_retry_options)
Http::Request.create_faraday_client(@endpoint, @auth_headers, faraday_options, faraday_retry_options,
timeout: timeout)
end

initialize_routes(client: @client, defaults: @defaults)
Expand All @@ -42,14 +43,14 @@ def create_paginator(request, params = {})
Paginator.new(request, params)
end

def self.from_api_key(api_key, endpoint: nil, wait_for_action_attempt: true, faraday_options: {}, faraday_retry_options: {})
def self.from_api_key(api_key, endpoint: nil, wait_for_action_attempt: true, timeout: nil, faraday_options: {}, faraday_retry_options: {})
new(api_key: api_key, endpoint: endpoint, wait_for_action_attempt: wait_for_action_attempt,
faraday_options: faraday_options, faraday_retry_options: faraday_retry_options)
timeout: timeout, faraday_options: faraday_options, faraday_retry_options: faraday_retry_options)
end

def self.from_personal_access_token(personal_access_token, workspace_id, endpoint: nil, wait_for_action_attempt: true, faraday_options: {}, faraday_retry_options: {})
def self.from_personal_access_token(personal_access_token, workspace_id, endpoint: nil, wait_for_action_attempt: true, timeout: nil, faraday_options: {}, faraday_retry_options: {})
new(personal_access_token: personal_access_token, workspace_id: workspace_id, endpoint: endpoint,
wait_for_action_attempt: wait_for_action_attempt, faraday_options: faraday_options, faraday_retry_options: faraday_retry_options)
wait_for_action_attempt: wait_for_action_attempt, timeout: timeout, faraday_options: faraday_options, faraday_retry_options: faraday_retry_options)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/seam/options.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

require_relative "default_endpoint"
require_relative "defaults"

module Seam
module Http
Expand Down
10 changes: 8 additions & 2 deletions lib/seam/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@

require "faraday"
require "faraday/retry"
require_relative "defaults"
require_relative "lts_version"
require_relative "version"
require_relative "paginator"

module Seam
module Http
module Request
def self.create_faraday_client(endpoint, auth_headers, faraday_options = {}, faraday_retry_options = {})
def self.create_faraday_client(endpoint, auth_headers, faraday_options = {}, faraday_retry_options = {},
timeout: nil)
timeout ||= Seam::DEFAULT_TIMEOUT

default_options = {
url: endpoint,
headers: auth_headers.merge(default_headers)
headers: auth_headers.merge(default_headers),
# open_timeout bounds the connect phase, which timeout does not cover.
request: {timeout: timeout, open_timeout: timeout}
}

options = deep_merge(default_options, faraday_options)
Expand Down
4 changes: 2 additions & 2 deletions spec/seam_client/faraday_options_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
endpoint: endpoint,
faraday_options: {
headers: {"Custom-Header" => "Test-Value"},
request: {timeout: 30}
request: {timeout: 45}
}
)

expect(seam.client.headers["Custom-Header"]).to eq("Test-Value")
expect(seam.client.options.timeout).to eq(30)
expect(seam.client.options.timeout).to eq(45)
end

it "keeps the auth and SDK headers when custom headers are given" do
Expand Down
56 changes: 56 additions & 0 deletions spec/seam_client/timeout_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# frozen_string_literal: true

RSpec.describe Seam::Http::SingleWorkspace, :fake do
describe "timeout" do
it "defaults to 30 seconds" do
seam = described_class.new(api_key: seed["seam_apikey1_token"], endpoint: endpoint)

expect(seam.client.options.timeout).to eq(30)
expect(seam.client.options.open_timeout).to eq(30)
end

it "can be overridden with the timeout option" do
seam = described_class.new(api_key: seed["seam_apikey1_token"], endpoint: endpoint, timeout: 60)

expect(seam.client.options.timeout).to eq(60)
expect(seam.client.options.open_timeout).to eq(60)
end

it "can be overridden by the factory methods" do
seam = described_class.from_api_key(seed["seam_apikey1_token"], endpoint: endpoint, timeout: 60)

expect(seam.client.options.timeout).to eq(60)
end

it "gives faraday_options the last word" do
seam = described_class.new(
api_key: seed["seam_apikey1_token"],
endpoint: endpoint,
timeout: 60,
faraday_options: {request: {timeout: 5}}
)

expect(seam.client.options.timeout).to eq(5)
expect(seam.client.options.open_timeout).to eq(60)
end

it "does not apply to a client passed in by the caller" do
client = Faraday.new(url: endpoint)
seam = described_class.new(client: client)

expect(seam.client.options.timeout).to be_nil
end
end

describe "a request that exceeds the timeout" do
let(:url) { "#{Seam::DEFAULT_ENDPOINT}/devices/list" }

it "raises Faraday::TimeoutError" do
stub_request(:post, url).to_timeout

seam = Seam.new(api_key: "seam_some_api_key", timeout: 1)

expect { seam.devices.list }.to raise_error(Faraday::ConnectionFailed)
end
end
end
Loading