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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3f293dd460a9b6468a63c41cabe277f8a948b419
4
- data.tar.gz: 07307d95d8574a28775a03549afa110d233d730e
3
+ metadata.gz: c7cc02538db7ad911dd5b61aa6eab9f9d651ac64
4
+ data.tar.gz: e81e18d1337ccfeae94260e8ed40e2319377f7aa
5
5
  SHA512:
6
- metadata.gz: 6209f4db889a5a4c29cf83476509405e56f796180f2024f5945057ce633eedbfde0dbcc4048684947aef4c981071cb1fa99caab3bd142672e7a8dc0c0c98f507
7
- data.tar.gz: a5231899ad5ded76359d19f625e921114aa4f3dd4aa1dc8046ec1179f398f2eaf94b4cddbcac7ca65bd66c33fc7aa5d86b03a762aa0f629811f6b3ae7f56023c
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
- attr_accessor :jobs, :job_to_worker, :worker_to_job, :job_to_condition, :mutex, :registration_complete, :workers_terminated, :stderr_buffer
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
- 'action' => 'invoke',
173
- 'job_id' => job.id,
174
- 'task' => task
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
- @jobs.find { |_job_id, job| job.stage == 'production' }.blank?
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
- exit_status == 0 ? update_machine_state('FINISHED') : update_machine_state('DEAD')
182
- # @manager.worker_died(Actor.current, exit_status) if exit_status != 0
183
- @manager.workers_terminated.signal('completed') if @manager.present? && @manager.alive? && @manager.all_workers_finished?
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
- return if exit_status == 0
189
- error_message = "worker #{@job_id} task failed with exit status #{exit_status.inspect} "
190
- raise(CapistranoMulticonfigParallel::CelluloidWorker::TaskFailed.new(error_message), error_message)
191
- end
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
- return if @runner_status.exit_status.blank?
60
+ exit_status = @runner_status.exit_status
61
+ return if exit_status.blank?
61
62
  @timer.cancel
62
- @job.exit_status = @runner_status.exit_status
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(@job.exit_status)
66
+ @actor.async.notify_finished(exit_status)
67
67
  elsif @synchronicity == :sync
68
- @actor.notify_finished(@job.exit_status)
68
+ @actor.notify_finished(exit_status)
69
69
  end
70
70
  end
71
71
  end
@@ -62,7 +62,6 @@ module CapistranoMulticonfigParallel
62
62
 
63
63
  def watch_handler(process)
64
64
  @process ||= process
65
- process_runner.check_exit_status
66
65
  end
67
66
 
68
67
  def io_callback(io, data)
@@ -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, :bundler_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
- worker_obj.present? && worker_obj.alive? ? worker_obj.worker_state : default
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? || dead? || exit_status.present?
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
- worker.blank? || !worker.alive?
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
- <<-CMD
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=#{debug_websocket?} LOG_FILE=#{websocket_config.fetch('log_file_path', nil)} #{bundle_gemfile_env(@job_final_gemfile)} bundle exec cap #{job_stage} #{capistrano_action} #{environment_options}"
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
@@ -10,7 +10,7 @@ module CapistranoMulticonfigParallel
10
10
  MAJOR = 2
11
11
  MINOR = 0
12
12
  TINY = 0
13
- PRE = 'rc1'
13
+ PRE = 'rc2'
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
16
16
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano_multiconfig_parallel
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc1
4
+ version: 2.0.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - bogdanRada