From a3f63f84843d2dd630c9b618b272b22a4958083b Mon Sep 17 00:00:00 2001 From: "gocardless-ci-robot[bot]" <123969075+gocardless-ci-robot[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2026 10:49:49 +0000 Subject: [PATCH] Changes generated by 811a5c904f03659e41505c41b790f52df39fadd3 This commit was automatically created from gocardless/client-library-templates@811a5c904f03659e41505c41b790f52df39fadd3 by the `push-files` action. Workflow run: https://github.com/gocardless/client-library-templates/actions/runs/40309967057 --- README.md | 2 +- lib/gocardless_pro/api_service.rb | 6 +++++- lib/gocardless_pro/client.rb | 2 +- spec/api_service_spec.rb | 26 ++++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3f08997..8e358b4 100644 --- a/README.md +++ b/README.md @@ -192,7 +192,7 @@ end If the client is unable to connect to GoCardless, an appropriate exception will be raised, for example: -* `Faraday::TimeoutError`, in case of a timeout +* `Faraday::TimeoutError`, in case of a timeout (requests time out after 60 seconds by default; change this with the `connection_options` client option, e.g. `connection_options: { request: { timeout: 10 } }`) * `Faraday::ConnectionFailed`, in case of a connection issue (e.g. problems with DNS resolution) * `GoCardlessPro::ApiError`, for `5xx` errors returned from our infrastructure, but not by the API itself diff --git a/lib/gocardless_pro/api_service.rb b/lib/gocardless_pro/api_service.rb index 6a331f3..4d60251 100644 --- a/lib/gocardless_pro/api_service.rb +++ b/lib/gocardless_pro/api_service.rb @@ -9,6 +9,9 @@ module GoCardlessPro # GoCardless API class ApiService + # Seconds to wait for a response when `connection_options` doesn't set `request: { timeout: ... }` + DEFAULT_TIMEOUT = 60 + attr_reader :on_idempotency_conflict # Initialize an APIService @@ -22,8 +25,9 @@ def initialize(url, token, options = {}) root_url, @path_prefix = unpack_url(url) http_adapter = options[:http_adapter] || [:net_http] connection_options = options.fetch(:connection_options, {}) + request_options = { timeout: DEFAULT_TIMEOUT }.merge(connection_options.fetch(:request, {})) - @connection = Faraday.new(root_url, connection_options) do |faraday| + @connection = Faraday.new(root_url, connection_options.merge(request: request_options)) do |faraday| faraday.response :raise_gocardless_errors faraday.adapter(*http_adapter) diff --git a/lib/gocardless_pro/client.rb b/lib/gocardless_pro/client.rb index 79e97ac..7bc5e57 100644 --- a/lib/gocardless_pro/client.rb +++ b/lib/gocardless_pro/client.rb @@ -239,7 +239,7 @@ def webhooks # @option options [Symbol] :environment the environment to connect to - one of `:live` or `:sandbox`. # @option options [Symbol] :access_token the API token # @option options [Symbol] :url the full URL used to make requests to. If you specify this, it will be used over the `environment` option. - # @option options [Symbol] :connection_options `Faraday` connection options hash, e.g. `{ request: { timeout: 3 } }`. + # @option options [Symbol] :connection_options `Faraday` connection options hash, e.g. `{ request: { timeout: 3 } }`. Requests time out after 60 seconds unless `request: { timeout: ... }` is set. # @return [Client] A client configured to use the API with HTTP Basic # authentication. # diff --git a/spec/api_service_spec.rb b/spec/api_service_spec.rb index e7c114c..c6b76e6 100644 --- a/spec/api_service_spec.rb +++ b/spec/api_service_spec.rb @@ -14,6 +14,32 @@ } end + describe 'request timeout' do + let(:connection) { service.instance_variable_get(:@connection) } + + it 'defaults to 60 seconds' do + expect(GoCardlessPro::ApiService::DEFAULT_TIMEOUT).to eq(60) + expect(connection.options.timeout).to eq(60) + end + + context 'when connection_options sets a timeout' do + let(:options) { { connection_options: { request: { timeout: 5 } } } } + + it 'uses the configured timeout' do + expect(connection.options.timeout).to eq(5) + end + end + + context 'when connection_options sets other request options' do + let(:options) { { connection_options: { request: { open_timeout: 2 } } } } + + it 'keeps the default timeout' do + expect(connection.options.timeout).to eq(60) + expect(connection.options.open_timeout).to eq(2) + end + end + end + it 'uses basic auth' do stub = stub_request(:get, 'https://api.example.com/customers'). with(headers: { 'Authorization' => 'Bearer secret_token' }).