capistrano_multiconfig_parallel 2.0.0.rc1 → 2.0.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|