diff --git a/README.md b/README.md index e0697050..6147a2df 100644 --- a/README.md +++ b/README.md @@ -600,6 +600,19 @@ require 'docker' Docker::Container.all({}, Docker::Connection.new('tcp://example.com:2375', {})) ``` +## Keep connection to Docker alive + +Each call will be done through a new established HTTP connection. This can be a bit slow if doing a lot of calls. You can keep the HTTP connection alive like this: + +```ruby +connection = Docker::Connection.new("tcp://example.com:1000", cache_resource: true) +``` + +And then use the connection on eahc call like this: +```ruby +container = Docker::Image.get(id, {}, connection) +``` + ## Rake Task To create images through `rake`, a DSL task is provided. For example: diff --git a/lib/docker/connection.rb b/lib/docker/connection.rb index 7537f90e..5f5358ef 100644 --- a/lib/docker/connection.rb +++ b/lib/docker/connection.rb @@ -1,3 +1,5 @@ +require 'json' + # This class represents a Connection to a Docker server. The Connection is # immutable in that once the url and options is set they cannot be changed. class Docker::Connection @@ -29,13 +31,24 @@ def initialize(url, opts) end end - # The actual client that sends HTTP methods to the Docker server. This value - # is not cached, since doing so may cause socket errors after bad requests. + # The actual client that sends HTTP methods to the Docker server. def resource - Excon.new(url, options) + if @options[:cache_resource] + @resource ||= new_excon + else + new_excon + end end private :resource + def new_excon + Excon.new(url, options) + end + + def reset_resource + @resource = nil + end + # Send a request to the server with the ` def request(*args, &block) retries ||= 0 @@ -44,6 +57,8 @@ def request(*args, &block) begin resource.request(request).body rescue Excon::Errors::BadRequest => ex + reset_resource + if retries < 2 response_cause = '' begin diff --git a/spec/docker/connection_spec.rb b/spec/docker/connection_spec.rb index 6cb725a9..c00edc5f 100644 --- a/spec/docker/connection_spec.rb +++ b/spec/docker/connection_spec.rb @@ -64,7 +64,23 @@ end describe '#resource' do + subject { described_class.new('http://localhost:4243', cache_resource: true) } + its(:resource) { should be_a Excon::Connection } + + it 'reuses the same connection' do + previous_resource = subject.__send__(:resource) + expect(subject.__send__(:resource).__id__).to eq previous_resource.__id__ + end + + it 'spawns a new Excon::Connection if encountering a bad request' do + previous_resource = subject.__send__(:resource) + response = Excon::Response.new + error = Excon::Errors::BadRequest.new('Hello world', nil, response) + expect(previous_resource).to receive(:request).and_raise(error) + expect { subject.request(:get, '/test', {all: true}, {}) }.to raise_error(Docker::Error::ClientError) + expect(subject.__send__(:resource).__id__).not_to eq previous_resource.__id__ + end end describe '#request' do