Skip to content
This repository was archived by the owner on Jun 2, 2021. It is now read-only.

Commit 053c1f2

Browse files
author
Derik Evangelista
authored
v3(services): delete SI asynchronously (cloudfoundry#1733)
* v3(services): delete SI asynchronously [finishes #171726806](https://www.pivotaltracker.com/story/show/171726806)
1 parent c10832b commit 053c1f2

10 files changed

Lines changed: 618 additions & 465 deletions

app/actions/v3/service_instance_delete.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ def synchronous_destroy(service_instance, lock)
4040
def asynchronous_destroy(service_instance)
4141
delete_job = V3::DeleteServiceInstanceJob.new(
4242
service_instance.guid,
43-
:deprovision,
4443
service_event_repository.user_audit_info)
4544

4645
pollable_job = Jobs::Enqueuer.new(delete_job, queue: Jobs::Queues.generic).enqueue_pollable

app/jobs/v3/create_service_instance_job.rb

Lines changed: 11 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -1,152 +1,28 @@
1-
require 'jobs/reoccurring_job'
1+
require 'jobs/v3/service_instance_async_job'
22

33
module VCAP::CloudController
44
module V3
5-
class CreateServiceInstanceJob < VCAP::CloudController::Jobs::ReoccurringJob
6-
attr_reader :warnings
7-
5+
class CreateServiceInstanceJob < ServiceInstanceAsyncJob
86
def initialize(service_instance_guid, arbitrary_parameters: {}, user_audit_info:)
9-
super()
10-
@service_instance_guid = service_instance_guid
11-
@arbitrary_parameters = arbitrary_parameters
12-
@user_audit_info = user_audit_info
13-
@start_time = Time.now
14-
@first_time = true
15-
@warnings = []
16-
end
17-
18-
def perform
19-
client = VCAP::Services::ServiceClientProvider.provide({ instance: service_instance })
20-
21-
if first_time
22-
compute_maximum_duration
23-
send_provision_request(client)
24-
compatibility_checks
25-
@first_time = false
26-
end
27-
28-
gone! if service_instance.nil?
29-
30-
operation_in_progress = service_instance.last_operation.type
31-
aborted! if operation_in_progress != 'create'
32-
33-
if service_instance.operation_in_progress?
34-
fetch_last_operation(client)
35-
end
36-
37-
if service_instance.last_operation.state == 'succeeded'
38-
record_event(service_instance, @arbitrary_parameters)
39-
finish
40-
elsif service_instance.last_operation.state == 'failed'
41-
operation_failed!(service_instance.last_operation.description)
42-
end
43-
end
44-
45-
def handle_timeout
46-
service_instance.save_and_update_operation(
47-
last_operation: {
48-
state: 'failed',
49-
description: 'Service Broker failed to provision within the required time.',
50-
}
51-
)
7+
super(service_instance_guid, user_audit_info)
8+
@request_attr = arbitrary_parameters
529
end
5310

54-
def job_name_in_configuration
55-
:service_instance_create
11+
def operation
12+
:provision
5613
end
5714

58-
def max_attempts
59-
1
15+
def operation_type
16+
'create'
6017
end
6118

62-
def resource_type
63-
'service_instances'
64-
end
65-
66-
def resource_guid
67-
service_instance_guid
68-
end
69-
70-
def display_name
71-
'service_instance.create'
72-
end
73-
74-
private
75-
76-
attr_reader :service_instance_guid, :arbitrary_parameters, :first_time
77-
78-
def compute_maximum_duration
79-
max_poll_duration_on_plan = service_instance.service_plan.try(:maximum_polling_duration)
80-
self.maximum_duration_seconds = max_poll_duration_on_plan if max_poll_duration_on_plan
81-
end
82-
83-
def send_provision_request(client)
84-
broker_response = client.provision(
19+
def send_broker_request(client)
20+
client.provision(
8521
service_instance,
8622
accepts_incomplete: true,
87-
arbitrary_parameters: arbitrary_parameters,
23+
arbitrary_parameters: @request_attr,
8824
maintenance_info: service_instance.service_plan.maintenance_info
8925
)
90-
91-
service_instance.save_with_new_operation(broker_response[:instance], broker_response[:last_operation])
92-
rescue => e
93-
service_instance.save_with_new_operation({}, {
94-
type: 'create',
95-
state: 'failed',
96-
description: e.message,
97-
})
98-
raise e
99-
end
100-
101-
def fetch_last_operation(client)
102-
last_operation_result = client.fetch_service_instance_last_operation(service_instance)
103-
self.polling_interval_seconds = last_operation_result[:retry_after] if last_operation_result[:retry_after]
104-
105-
service_instance.save_and_update_operation(
106-
last_operation: last_operation_result[:last_operation].slice(:state, :description)
107-
)
108-
rescue HttpRequestError, HttpResponseError, Sequel::Error => e
109-
logger = Steno.logger('cc-background')
110-
logger.error("There was an error while fetching the service instance operation state: #{e}")
111-
end
112-
113-
def record_event(service_instance, request_attrs)
114-
Repositories::ServiceEventRepository.new(@user_audit_info).
115-
record_service_instance_event(:create, service_instance, request_attrs)
116-
end
117-
118-
def service_instance
119-
ManagedServiceInstance.first(guid: service_instance_guid)
120-
end
121-
122-
def compatibility_checks
123-
if service_instance.service_plan.service.volume_service? && volume_services_disabled?
124-
@warnings.push({ detail: ServiceInstance::VOLUME_SERVICE_WARNING })
125-
end
126-
127-
if service_instance.service_plan.service.route_service? && route_services_disabled?
128-
@warnings.push({ detail: ServiceInstance::ROUTE_SERVICE_WARNING })
129-
end
130-
end
131-
132-
def volume_services_disabled?
133-
!VCAP::CloudController::Config.config.get(:volume_services_enabled)
134-
end
135-
136-
def route_services_disabled?
137-
!VCAP::CloudController::Config.config.get(:route_services_enabled)
138-
end
139-
140-
def gone!
141-
raise CloudController::Errors::ApiError.new_from_details('ServiceInstanceNotFound', service_instance_guid)
142-
end
143-
144-
def aborted!
145-
raise CloudController::Errors::ApiError.new_from_details('UnableToPerform', 'Create', 'delete in progress')
146-
end
147-
148-
def operation_failed!(msg)
149-
raise CloudController::Errors::ApiError.new_from_details('ServiceInstanceProvisionFailed', msg)
15026
end
15127
end
15228
end

app/jobs/v3/delete_service_instance_job.rb

Lines changed: 20 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,40 @@
1-
require 'jobs/reoccurring_job'
1+
require 'jobs/v3/service_instance_async_job'
22

33
module VCAP::CloudController
44
module V3
5-
class DeleteServiceInstanceJob < VCAP::CloudController::Jobs::ReoccurringJob
6-
attr_reader :warnings
7-
8-
def initialize(guid, operation, audit_info)
9-
super()
10-
@service_instance_guid = guid
11-
@operation = operation
12-
@client_arguments = { accepts_incomplete: false }
13-
@user_audit_info = audit_info
14-
@warnings = []
15-
end
16-
17-
def perform
18-
client = VCAP::Services::ServiceClientProvider.provide({ instance: service_instance })
19-
20-
execute_request(client)
21-
22-
finish
23-
end
24-
25-
def job_name_in_configuration
26-
"service_instance_#{operation_type}"
5+
class DeleteServiceInstanceJob < ServiceInstanceAsyncJob
6+
def initialize(guid, audit_info)
7+
super(guid, audit_info)
278
end
289

29-
def max_attempts
30-
1
10+
def send_broker_request(client)
11+
client.deprovision(service_instance, { accepts_incomplete: true })
3112
end
3213

33-
def resource_type
34-
'service_instances'
14+
def operation_succeeded
15+
ServiceInstance.db.transaction do
16+
service_instance.lock!
17+
service_instance.last_operation&.destroy
18+
service_instance.destroy
19+
end
3520
end
3621

37-
def resource_guid
38-
service_instance_guid
22+
def operation
23+
:deprovision
3924
end
4025

41-
def display_name
42-
"service_instance.#{operation_type}"
26+
def operation_type
27+
'delete'
4328
end
4429

4530
private
4631

47-
attr_reader :service_instance_guid
48-
49-
def service_instance
50-
ManagedServiceInstance.first(guid: @service_instance_guid)
51-
end
52-
53-
def execute_request(client)
54-
broker_response = client.public_send(
55-
@operation,
56-
service_instance,
57-
@client_arguments
58-
)
59-
60-
if broker_response.dig(:last_operation, :state) == 'succeeded'
61-
ServiceInstance.db.transaction do
62-
si = service_instance
63-
service_instance.lock!
64-
service_instance.last_operation&.destroy
65-
service_instance.destroy
66-
record_event(si, nil)
67-
end
68-
end
69-
rescue => e
70-
service_instance.save_with_new_operation({}, {
71-
type: operation_type,
72-
state: 'failed',
73-
description: e.message,
74-
})
75-
raise e
76-
end
77-
78-
def record_event(service_instance, request_attrs)
79-
Repositories::ServiceEventRepository.new(@user_audit_info).
80-
record_service_instance_event(:delete, service_instance, request_attrs)
32+
def gone!
33+
finish
8134
end
8235

83-
def operation_type
84-
case @operation
85-
when :deprovision
86-
'delete'
87-
else
88-
''
89-
end
36+
def compatibility_checks
37+
nil
9038
end
9139
end
9240
end

0 commit comments

Comments
 (0)