Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache resource #555

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
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
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
21 changes: 18 additions & 3 deletions lib/docker/connection.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
16 changes: 16 additions & 0 deletions spec/docker/connection_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down