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
8 changes: 4 additions & 4 deletions app/controllers/v3/droplets_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ def index
invalid_param!(message.errors.full_messages) unless message.valid?

if app_nested?
app, dataset = DropletListFetcher.fetch_for_app(message)
app, dataset = DropletListFetcher.fetch_for_app(message, eager_loaded_associations: Presenters::V3::DropletPresenter.associated_resources)
app_not_found! unless app && permission_queryer.can_read_from_space?(app.space.id, app.space.organization_id)
elsif package_nested?
package, dataset = DropletListFetcher.fetch_for_package(message)
package, dataset = DropletListFetcher.fetch_for_package(message, eager_loaded_associations: Presenters::V3::DropletPresenter.associated_resources)
package_not_found! unless package && permission_queryer.can_read_from_space?(package.space.id, package.space.organization_id)
else
dataset = if permission_queryer.can_read_globally?
DropletListFetcher.fetch_all(message)
DropletListFetcher.fetch_all(message, eager_loaded_associations: Presenters::V3::DropletPresenter.associated_resources)
else
DropletListFetcher.fetch_for_spaces(message, permission_queryer.readable_space_guids)
DropletListFetcher.fetch_for_spaces(message, permission_queryer.readable_space_guids, eager_loaded_associations: Presenters::V3::DropletPresenter.associated_resources)
end
end

Expand Down
22 changes: 12 additions & 10 deletions app/fetchers/droplet_list_fetcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,34 @@
module VCAP::CloudController
class DropletListFetcher < BaseListFetcher
class << self
def fetch_all(message)
dataset = DropletModel.dataset
filter(message, nil, nil, dataset)
def fetch_all(message, eager_loaded_associations: [])
filter(message, nil, nil, droplet_dataset(eager_loaded_associations))
end

def fetch_for_spaces(message, space_guids)
dataset = DropletModel.dataset
filter(message, nil, space_guids, dataset)
def fetch_for_spaces(message, space_guids, eager_loaded_associations: [])
filter(message, nil, space_guids, droplet_dataset(eager_loaded_associations))
end

def fetch_for_app(message)
def fetch_for_app(message, eager_loaded_associations: [])
app = AppModel.where(guid: message.app_guid).first
return nil unless app

[app, filter(message, app, nil, app.droplets_dataset)]
[app, filter(message, app, nil, droplet_dataset(eager_loaded_associations, app.droplets_dataset))]
end

def fetch_for_package(message)
def fetch_for_package(message, eager_loaded_associations: [])
package = PackageModel.where(guid: message.package_guid).first
return nil unless package

[package, filter(message, nil, nil, package.droplets_dataset)]
[package, filter(message, nil, nil, droplet_dataset(eager_loaded_associations, package.droplets_dataset))]
end

private

def droplet_dataset(eager_loaded_associations, dataset=DropletModel.dataset)
dataset.eager(eager_loaded_associations)
end

def filter(message, app, space_guids, dataset)
if message.requested?(:current) && app
dataset = dataset.extension(:null_dataset)
Expand Down
7 changes: 7 additions & 0 deletions app/presenters/v3/droplet_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ module V3
class DropletPresenter < BasePresenter
include VCAP::CloudController::Presenters::Mixins::MetadataPresentationHelpers

class << self
# :labels and :annotations come from MetadataPresentationHelpers
def associated_resources
super + [{ buildpack_lifecycle_data: :buildpack_lifecycle_buildpacks }, :cnb_lifecycle_data]
end
end

def to_hash
{
guid: droplet.guid,
Expand Down
18 changes: 18 additions & 0 deletions spec/request/droplets_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,24 @@
droplet2.buildpack_lifecycle_data.update(buildpacks: ['http://buildpack.git.url.com'], stack: 'stack-2')
end

context 'eager loading' do
let!(:docker_droplet_1) { VCAP::CloudController::DropletModel.make(:docker, app_guid: app_model.guid) }
let!(:docker_droplet_2) { VCAP::CloudController::DropletModel.make(:docker, app_guid: app_model.guid) }
let(:get_droplets) { -> { get '/v3/droplets', nil, developer_headers } }

it 'eager loads associated data needed to present droplets' do
expect { get_droplets.call }.to have_queried_db_times(/SELECT .* FROM .droplets. /i, 1)
expect(last_response.status).to eq(200)
expect(parsed_response['resources'].count).to eq(4)

expect { get_droplets.call }.to have_queried_db_times(/SELECT .* FROM .droplet_annotations. /i, 1) # instead of 4 w/o eager loading
expect { get_droplets.call }.to have_queried_db_times(/SELECT .* FROM .droplet_labels. /i, 1) # instead of 4 w/o eager loading
expect { get_droplets.call }.to have_queried_db_times(/SELECT .* FROM .buildpack_lifecycle_data. /i, 1) # instead of 4 w/o eager loading
expect { get_droplets.call }.to have_queried_db_times(/SELECT .* FROM .buildpack_lifecycle_buildpacks. /i, 1) # instead of 2 w/o eager loading
expect { get_droplets.call }.to have_queried_db_times(/SELECT .* FROM .cnb_lifecycle_data. /i, 1) # instead of 2 w/o eager loading
end
end

it_behaves_like 'list query endpoint' do
let(:request) { 'v3/droplets' }
let(:message) { VCAP::CloudController::DropletsListMessage }
Expand Down