Skip to content

Commit 4395173

Browse files
committed
Reduce db calls when presenting droplets
Eager load metadata, buildpack_lifecycle_buildpacks, and buildpack_lifecycle_data.
1 parent c34630a commit 4395173

File tree

4 files changed

+38
-14
lines changed

4 files changed

+38
-14
lines changed

app/controllers/v3/droplets_controller.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@ def index
2222
invalid_param!(message.errors.full_messages) unless message.valid?
2323

2424
if app_nested?
25-
app, dataset = DropletListFetcher.fetch_for_app(message)
25+
app, dataset = DropletListFetcher.fetch_for_app(message, eager_loaded_associations: Presenters::V3::DropletPresenter.associated_resources)
2626
app_not_found! unless app && permission_queryer.can_read_from_space?(app.space.id, app.space.organization_id)
2727
elsif package_nested?
28-
package, dataset = DropletListFetcher.fetch_for_package(message)
28+
package, dataset = DropletListFetcher.fetch_for_package(message, eager_loaded_associations: Presenters::V3::DropletPresenter.associated_resources)
2929
package_not_found! unless package && permission_queryer.can_read_from_space?(package.space.id, package.space.organization_id)
3030
else
3131
dataset = if permission_queryer.can_read_globally?
32-
DropletListFetcher.fetch_all(message)
32+
DropletListFetcher.fetch_all(message, eager_loaded_associations: Presenters::V3::DropletPresenter.associated_resources)
3333
else
34-
DropletListFetcher.fetch_for_spaces(message, permission_queryer.readable_space_guids)
34+
DropletListFetcher.fetch_for_spaces(message, permission_queryer.readable_space_guids, eager_loaded_associations: Presenters::V3::DropletPresenter.associated_resources)
3535
end
3636
end
3737

app/fetchers/droplet_list_fetcher.rb

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,34 @@
33
module VCAP::CloudController
44
class DropletListFetcher < BaseListFetcher
55
class << self
6-
def fetch_all(message)
7-
dataset = DropletModel.dataset
8-
filter(message, nil, nil, dataset)
6+
def fetch_all(message, eager_loaded_associations: [])
7+
filter(message, nil, nil, droplet_dataset(eager_loaded_associations))
98
end
109

11-
def fetch_for_spaces(message, space_guids)
12-
dataset = DropletModel.dataset
13-
filter(message, nil, space_guids, dataset)
10+
def fetch_for_spaces(message, space_guids, eager_loaded_associations: [])
11+
filter(message, nil, space_guids, droplet_dataset(eager_loaded_associations))
1412
end
1513

16-
def fetch_for_app(message)
14+
def fetch_for_app(message, eager_loaded_associations: [])
1715
app = AppModel.where(guid: message.app_guid).first
1816
return nil unless app
1917

20-
[app, filter(message, app, nil, app.droplets_dataset)]
18+
[app, filter(message, app, nil, droplet_dataset(eager_loaded_associations, app.droplets_dataset))]
2119
end
2220

23-
def fetch_for_package(message)
21+
def fetch_for_package(message, eager_loaded_associations: [])
2422
package = PackageModel.where(guid: message.package_guid).first
2523
return nil unless package
2624

27-
[package, filter(message, nil, nil, package.droplets_dataset)]
25+
[package, filter(message, nil, nil, droplet_dataset(eager_loaded_associations, package.droplets_dataset))]
2826
end
2927

3028
private
3129

30+
def droplet_dataset(eager_loaded_associations, dataset=DropletModel.dataset)
31+
dataset.eager(eager_loaded_associations)
32+
end
33+
3234
def filter(message, app, space_guids, dataset)
3335
if message.requested?(:current) && app
3436
dataset = dataset.extension(:null_dataset)

app/presenters/v3/droplet_presenter.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ module V3
77
class DropletPresenter < BasePresenter
88
include VCAP::CloudController::Presenters::Mixins::MetadataPresentationHelpers
99

10+
class << self
11+
# :labels and :annotations come from MetadataPresentationHelpers
12+
def associated_resources
13+
super + [{ buildpack_lifecycle_data: :buildpack_lifecycle_buildpacks }]
14+
end
15+
end
16+
1017
def to_hash
1118
{
1219
guid: droplet.guid,

spec/request/droplets_spec.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,21 @@
607607
droplet2.buildpack_lifecycle_data.update(buildpacks: ['http://buildpack.git.url.com'], stack: 'stack-2')
608608
end
609609

610+
context 'eager loading' do
611+
let(:get_droplets) { -> { get '/v3/droplets', nil, developer_headers } }
612+
613+
it 'eager loads associated data needed to present droplets' do
614+
expect { get_droplets.call }.to have_queried_db_times(/SELECT .* FROM .droplets. /i, 1)
615+
expect(last_response.status).to eq(200)
616+
expect(parsed_response['resources'].count).to eq(2)
617+
618+
expect { get_droplets.call }.to have_queried_db_times(/SELECT .* FROM .droplet_annotations. /i, 1) # instead of 2 w/o eager loading
619+
expect { get_droplets.call }.to have_queried_db_times(/SELECT .* FROM .droplet_labels. /i, 1) # instead of 2 w/o eager loading
620+
expect { get_droplets.call }.to have_queried_db_times(/SELECT .* FROM .buildpack_lifecycle_buildpacks. /i, 1) # instead of 2 w/o eager loading
621+
expect { get_droplets.call }.to have_queried_db_times(/SELECT .* FROM .buildpack_lifecycle_data. /i, 1) # instead of 2 w/o eager loading
622+
end
623+
end
624+
610625
it_behaves_like 'list query endpoint' do
611626
let(:request) { 'v3/droplets' }
612627
let(:message) { VCAP::CloudController::DropletsListMessage }

0 commit comments

Comments
 (0)