capistrano_multiconfig_parallel 2.0.0.rc1 → 2.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/capistrano_multiconfig_parallel/celluloid/celluloid_manager.rb +22 -9
- data/lib/capistrano_multiconfig_parallel/celluloid/celluloid_worker.rb +20 -11
- data/lib/capistrano_multiconfig_parallel/celluloid/process_runner.rb +5 -5
- data/lib/capistrano_multiconfig_parallel/classes/child_process_status.rb +0 -1
- data/lib/capistrano_multiconfig_parallel/classes/job.rb +22 -8
- data/lib/capistrano_multiconfig_parallel/classes/job_command.rb +6 -3
- data/lib/capistrano_multiconfig_parallel/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c7cc02538db7ad911dd5b61aa6eab9f9d651ac64
|
4
|
+
data.tar.gz: e81e18d1337ccfeae94260e8ed40e2319377f7aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f69ea91b5e891f4bd5186506734582c6d70785650f7ea9c08c9cc091bbe1bc084739084fe5c8a3277d99038f74d206087335714bacdebf2da11c41c8baa74ee
|
7
|
+
data.tar.gz: 4848c50cabcf6a0daa0f72bb9358f81aa49769746c9748e761954510b42c4682f4dbce620943adcdc06047679c39028dfb9fb82c3409376279007add787a6425
|
@@ -6,7 +6,7 @@ module CapistranoMulticonfigParallel
|
|
6
6
|
# manager class that handles workers
|
7
7
|
class CelluloidManager
|
8
8
|
include CapistranoMulticonfigParallel::BaseActorHelper
|
9
|
-
|
9
|
+
attr_accessor :jobs, :job_to_worker, :worker_to_job, :job_to_condition, :mutex, :registration_complete, :workers_terminated, :stderr_buffer
|
10
10
|
|
11
11
|
attr_reader :worker_supervisor, :workers
|
12
12
|
trap_exit :worker_died
|
@@ -40,11 +40,11 @@ module CapistranoMulticonfigParallel
|
|
40
40
|
|
41
41
|
# call to send an actor
|
42
42
|
# a job
|
43
|
-
def delegate_job(job)
|
43
|
+
def delegate_job(job, old_job = "")
|
44
44
|
@jobs[job.id] = job
|
45
45
|
# debug(@jobs)
|
46
46
|
# start work and send it to the background
|
47
|
-
@workers.work(job, Actor.current)
|
47
|
+
@workers.work(job, Actor.current, old_job)
|
48
48
|
end
|
49
49
|
|
50
50
|
# call back from actor once it has received it's job
|
@@ -72,6 +72,7 @@ module CapistranoMulticonfigParallel
|
|
72
72
|
wait_task_confirmations
|
73
73
|
end
|
74
74
|
terminal_show
|
75
|
+
async.check_workers_done?
|
75
76
|
condition = @workers_terminated.wait
|
76
77
|
until condition.present?
|
77
78
|
sleep(0.1) # keep current thread alive
|
@@ -80,6 +81,17 @@ module CapistranoMulticonfigParallel
|
|
80
81
|
terminal_show
|
81
82
|
end
|
82
83
|
|
84
|
+
def check_workers_done?
|
85
|
+
Thread.new do
|
86
|
+
loop do
|
87
|
+
if Actor.current.alive? && all_workers_finished?
|
88
|
+
@workers_terminated.signal('completed')
|
89
|
+
break
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
83
95
|
def terminal_show
|
84
96
|
Celluloid::Actor[:terminal_server].async.notify_time_change(CapistranoMulticonfigParallel::TerminalTable.topic, type: 'output') if Celluloid::Actor[:terminal_server].alive?
|
85
97
|
end
|
@@ -169,10 +181,10 @@ module CapistranoMulticonfigParallel
|
|
169
181
|
worker = get_worker_for_job(job_id)
|
170
182
|
if worker.alive?
|
171
183
|
worker.publish_rake_event('approved' => 'yes',
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
184
|
+
'action' => 'invoke',
|
185
|
+
'job_id' => job.id,
|
186
|
+
'task' => task
|
187
|
+
)
|
176
188
|
end
|
177
189
|
end
|
178
190
|
end
|
@@ -191,7 +203,7 @@ module CapistranoMulticonfigParallel
|
|
191
203
|
|
192
204
|
def can_tag_staging?
|
193
205
|
@job_manager.can_tag_staging? && @job_manager.tag_staging_exists? &&
|
194
|
-
|
206
|
+
@jobs.find { |_job_id, job| job.stage == 'production' }.blank?
|
195
207
|
end
|
196
208
|
|
197
209
|
def dispatch_new_job(job, options = {})
|
@@ -201,7 +213,7 @@ module CapistranoMulticonfigParallel
|
|
201
213
|
new_job_options = job.options.except!('id', 'status', 'exit_status').merge('env_options' => job.env_options.merge(env_opts))
|
202
214
|
new_job = CapistranoMulticonfigParallel::Job.new(@job_manager, new_job_options.merge(options))
|
203
215
|
log_to_file("Trying to DiSPATCH new JOB #{new_job.inspect}")
|
204
|
-
async.delegate_job(new_job) unless job.rolling_back?
|
216
|
+
async.delegate_job(new_job, job) unless job.rolling_back?
|
205
217
|
end
|
206
218
|
|
207
219
|
# lookup status of job by asking actor running it
|
@@ -227,6 +239,7 @@ module CapistranoMulticonfigParallel
|
|
227
239
|
job.rollback_changes_to_application
|
228
240
|
@worker_to_job.delete(mailbox.address)
|
229
241
|
log_to_file("RESTARTING: worker job #{job.inspect} with mailbox #{mailbox.inspect} and #{mailbox.address.inspect} died for reason: #{reason}")
|
242
|
+
|
230
243
|
dispatch_new_job(job, skip_env_options: true, action: 'deploy:rollback')
|
231
244
|
end
|
232
245
|
end
|
@@ -26,7 +26,7 @@ module CapistranoMulticonfigParallel
|
|
26
26
|
:job, :manager, :job_id, :app_name, :env_name, :action_name, :env_options, :machine, :socket_connection, :task_argv,
|
27
27
|
:rake_tasks, :current_task_number, # tracking tasks
|
28
28
|
:successfull_subscription, :subscription_channel, :publisher_channel, # for subscriptions and publishing events
|
29
|
-
:job_termination_condition, :invocation_chain, :filename, :worker_log, :exit_status
|
29
|
+
:job_termination_condition, :invocation_chain, :filename, :worker_log, :exit_status, :old_job
|
30
30
|
]
|
31
31
|
|
32
32
|
attr_reader *CapistranoMulticonfigParallel::CelluloidWorker::ATTRIBUTE_LIST
|
@@ -35,13 +35,14 @@ module CapistranoMulticonfigParallel
|
|
35
35
|
def initialize(*args)
|
36
36
|
end
|
37
37
|
|
38
|
-
def work(job, manager)
|
38
|
+
def work(job, manager, old_job)
|
39
39
|
@job = job
|
40
|
+
@old_job = old_job
|
40
41
|
@job_id = job.id
|
41
42
|
@worker_state = job.status
|
42
43
|
@manager = manager
|
43
44
|
@job_confirmation_conditions = []
|
44
|
-
log_to_file("worker #{@job_id} received #{job.inspect}")
|
45
|
+
log_to_file("worker #{@job_id} received #{job.inspect} and #{old_job.inspect}")
|
45
46
|
@subscription_channel = "#{CapistranoSentinel::RequestHooks::PUBLISHER_PREFIX}#{@job_id}"
|
46
47
|
@machine = CapistranoMulticonfigParallel::StateMachine.new(@job, Actor.current)
|
47
48
|
@manager.setup_worker_conditions(@job)
|
@@ -60,6 +61,9 @@ module CapistranoMulticonfigParallel
|
|
60
61
|
|
61
62
|
def start_task
|
62
63
|
log_to_file("exec worker #{@job_id} starts task and subscribes to #{@subscription_channel}")
|
64
|
+
if @old_job.present? && @old_job.is_a?(CapistranoMulticonfigParallel::Job)
|
65
|
+
@old_job.new_jobs_dispatched << @job.id
|
66
|
+
end
|
63
67
|
@socket_connection = CelluloidPubsub::Client.new(actor: Actor.current, enable_debug: debug_websocket?, channel: subscription_channel, log_file_path: websocket_config.fetch('log_file_path', nil))
|
64
68
|
end
|
65
69
|
|
@@ -111,6 +115,7 @@ module CapistranoMulticonfigParallel
|
|
111
115
|
|
112
116
|
def check_gitflow
|
113
117
|
return if @job.stage != 'staging' || !@manager.can_tag_staging? || !executed_task?(CapistranoMulticonfigParallel::GITFLOW_TAG_STAGING_TASK)
|
118
|
+
mark_for_dispatching_new_job
|
114
119
|
@manager.dispatch_new_job(@job, stage: 'production')
|
115
120
|
end
|
116
121
|
|
@@ -165,7 +170,6 @@ module CapistranoMulticonfigParallel
|
|
165
170
|
log_to_file("worker #{@job_id} triest to transition from #{@machine.state} to #{name}") unless options[:bundler]
|
166
171
|
@machine.go_to_transition(name.to_s, options)
|
167
172
|
error_message = "worker #{@job_id} task #{name} failed "
|
168
|
-
# @manager.worker_died(Actor.current, error_message) if job.failed?
|
169
173
|
raise(CapistranoMulticonfigParallel::CelluloidWorker::TaskFailed.new(error_message), error_message) if job.failed? # force worker to rollback
|
170
174
|
end
|
171
175
|
|
@@ -178,17 +182,22 @@ module CapistranoMulticonfigParallel
|
|
178
182
|
def finish_worker(exit_status)
|
179
183
|
log_to_file("worker #{job_id} tries to terminate with exit_status #{exit_status}")
|
180
184
|
@manager.mark_completed_remaining_tasks(@job) if Actor.current.alive?
|
181
|
-
|
182
|
-
|
183
|
-
|
185
|
+
update_machine_state('FINISHED') if exit_status == 0
|
186
|
+
@manager.workers_terminated.signal('completed') if !@job.marked_for_dispatching_new_job? && @manager.present? && @manager.alive? && @manager.all_workers_finished?
|
187
|
+
end
|
188
|
+
|
189
|
+
def mark_for_dispatching_new_job
|
190
|
+
@job.will_dispatch_new_job = @job.new_jobs_dispatched.size + 1 unless @job.rolling_back?
|
184
191
|
end
|
185
192
|
|
186
193
|
def notify_finished(exit_status)
|
194
|
+
mark_for_dispatching_new_job if exit_status != 0
|
195
|
+
@job.exit_status = exit_status
|
187
196
|
finish_worker(exit_status)
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
197
|
+
return if exit_status == 0
|
198
|
+
error_message = "worker #{@job_id} task failed with exit status #{exit_status.inspect} "
|
199
|
+
raise(CapistranoMulticonfigParallel::CelluloidWorker::TaskFailed.new(error_message), error_message)
|
200
|
+
end
|
192
201
|
|
193
202
|
# def inspect
|
194
203
|
# to_s
|
@@ -57,15 +57,15 @@ module CapistranoMulticonfigParallel
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def check_exit_status
|
60
|
-
|
60
|
+
exit_status = @runner_status.exit_status
|
61
|
+
return if exit_status.blank?
|
61
62
|
@timer.cancel
|
62
|
-
@
|
63
|
-
log_to_file("worker #{@job_id} startsnotify finished with exit status #{@job.exit_status.inspect}")
|
63
|
+
log_to_file("worker #{@job_id} startsnotify finished with exit status #{exit_status.inspect}")
|
64
64
|
if @actor.present? && @actor.respond_to?(:notify_finished)
|
65
65
|
if @actor.respond_to?(:async) && @synchronicity == :async
|
66
|
-
@actor.async.notify_finished(
|
66
|
+
@actor.async.notify_finished(exit_status)
|
67
67
|
elsif @synchronicity == :sync
|
68
|
-
@actor.notify_finished(
|
68
|
+
@actor.notify_finished(exit_status)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
@@ -6,7 +6,7 @@ module CapistranoMulticonfigParallel
|
|
6
6
|
include CapistranoMulticonfigParallel::ApplicationHelper
|
7
7
|
|
8
8
|
attr_reader :options, :application, :manager, :bundler_status
|
9
|
-
attr_writer :status, :exit_status, :
|
9
|
+
attr_writer :status, :exit_status, :bundler_status, :new_jobs_dispatched, :will_dispatch_new_job
|
10
10
|
|
11
11
|
delegate :stderr_buffer,
|
12
12
|
to: :manager
|
@@ -80,7 +80,7 @@ module CapistranoMulticonfigParallel
|
|
80
80
|
def worker_state
|
81
81
|
worker_obj = worker
|
82
82
|
default = status.to_s.upcase.red
|
83
|
-
|
83
|
+
worker_died? ? default : worker_obj.worker_state
|
84
84
|
end
|
85
85
|
|
86
86
|
def id
|
@@ -95,7 +95,10 @@ module CapistranoMulticonfigParallel
|
|
95
95
|
{ name: 'env_options', default: {} },
|
96
96
|
{ name: 'path', default: nil },
|
97
97
|
{ name: 'status', default: :unstarted },
|
98
|
-
{ name: 'exit_status', default: nil }
|
98
|
+
{ name: 'exit_status', default: nil },
|
99
|
+
{ name: 'bundler_status', default: nil },
|
100
|
+
{ name: 'new_jobs_dispatched', default: [] },
|
101
|
+
{ name: 'will_dispatch_new_job', default: nil },
|
99
102
|
].each do |hash|
|
100
103
|
define_method hash[:name] do
|
101
104
|
value = @options.fetch(hash[:name], hash[:default])
|
@@ -123,8 +126,19 @@ module CapistranoMulticonfigParallel
|
|
123
126
|
['deploy:rollback'].include?(action)
|
124
127
|
end
|
125
128
|
|
129
|
+
def marked_for_dispatching_new_job?
|
130
|
+
will_dispatch_new_job.to_i != new_jobs_dispatched.size
|
131
|
+
end
|
132
|
+
|
133
|
+
def new_jobs_dispatched_finished?
|
134
|
+
if marked_for_dispatching_new_job?
|
135
|
+
sleep(0.1) until will_dispatch_new_job.to_i == new_jobs_dispatched.size
|
136
|
+
end
|
137
|
+
true
|
138
|
+
end
|
139
|
+
|
126
140
|
def crashed?
|
127
|
-
worker_died? || failed? ||
|
141
|
+
worker_died? || failed? || exit_status.present?
|
128
142
|
end
|
129
143
|
|
130
144
|
def dead?
|
@@ -132,11 +146,11 @@ module CapistranoMulticonfigParallel
|
|
132
146
|
end
|
133
147
|
|
134
148
|
def worker_died?
|
135
|
-
|
149
|
+
dead? || worker == nil || worker.dead?
|
136
150
|
end
|
137
151
|
|
138
152
|
def work_done?
|
139
|
-
finished? || crashed?
|
153
|
+
new_jobs_dispatched_finished? && (finished? || crashed?)
|
140
154
|
end
|
141
155
|
|
142
156
|
def inspect
|
@@ -149,8 +163,8 @@ module CapistranoMulticonfigParallel
|
|
149
163
|
|
150
164
|
def to_json
|
151
165
|
hash = {}
|
152
|
-
%w(id app stage action task_arguments env_options status exit_status).each do |key|
|
153
|
-
hash[key] = send(key)
|
166
|
+
%w(id app stage action task_arguments env_options status exit_status bundler_status will_dispatch_new_job new_jobs_dispatched).each do |key|
|
167
|
+
hash[key] = send(key).inspect
|
154
168
|
end
|
155
169
|
hash
|
156
170
|
end
|
@@ -211,11 +211,14 @@ module CapistranoMulticonfigParallel
|
|
211
211
|
|
212
212
|
if rvm_enabled_for_job?
|
213
213
|
create_job_tempfile_command(command_text)
|
214
|
+
log_to_file "JOB #{@job_id} created Tempfile #{@tempfile.path} with contents #{File.read(@tempfile.path)}"
|
214
215
|
"ruby #{@tempfile.path}"
|
215
216
|
else
|
216
|
-
|
217
|
+
final_command=<<-CMD
|
217
218
|
cd #{job_path} && bundle exec ruby -e "#{command_text}"
|
218
219
|
CMD
|
220
|
+
log_to_file "JOB #{@job_id} prepared command #{final_command}"
|
221
|
+
final_command
|
219
222
|
end
|
220
223
|
end
|
221
224
|
|
@@ -224,7 +227,7 @@ module CapistranoMulticonfigParallel
|
|
224
227
|
prepare_application_for_deployment
|
225
228
|
# config_flags = CapistranoMulticonfigParallel.configuration_flags.merge("capistrano_version": job_capistrano_version)
|
226
229
|
environment_options = setup_command_line.join(' ')
|
227
|
-
command = "#{fetch_bundler_check_command(@job_final_gemfile)} && WEBSOCKET_LOGGING=#{
|
230
|
+
command = "#{fetch_bundler_check_command(@job_final_gemfile)} && WEBSOCKET_LOGGING=#{true} LOG_FILE=#{websocket_config.fetch('log_file_path', nil)} #{bundle_gemfile_env(@job_final_gemfile)} bundle exec cap #{job_stage} #{capistrano_action} #{environment_options}"
|
228
231
|
|
229
232
|
get_command_script(command)
|
230
233
|
end
|
@@ -239,7 +242,7 @@ module CapistranoMulticonfigParallel
|
|
239
242
|
end
|
240
243
|
|
241
244
|
def prepare_application_for_deployment
|
242
|
-
if ENV['MULTI_CAP_WEB_APP']
|
245
|
+
if ENV['MULTI_CAP_WEB_APP'].present?
|
243
246
|
bundler_worker = CapistranoMulticonfigParallel::BundlerWorker.new
|
244
247
|
result = bundler_worker.work(job)
|
245
248
|
end
|