process_bot 0.1.15 → 0.1.17

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3abcda452c729ce0582b53ff117aa7ec8658d16ad52f05f7ff1be5e383e2422
4
- data.tar.gz: 7499b97fa9e2ed082b739b241549baa4e511a5d0db0f024e921b4d174d842c20
3
+ metadata.gz: e0a67de01a927a07fc17e06814e4752b2da954eca493143f7850b18e5a5b1aa9
4
+ data.tar.gz: f0fc56095299f93a43a45549c9399118d4ddf7e5e112ce701baac8b86e1b3756
5
5
  SHA512:
6
- metadata.gz: 3680d58298af7cb511b3e5007abfafadfd3457b22230936e36f0925d6f8245b07de3116356f28b6beb18bf5cb36b86604b5bfeb323aa357adb2313d9ac20d733
7
- data.tar.gz: 4bbbafc629c0b3af2f47f1c82d3aab2bceeb003dd7820df85c5764427e654e96f08e232ee4e237f1df12e0c9a28fd807b0e9902ea1520c673902c79a95b0b3c8
6
+ metadata.gz: 5cad374bb6dacaa0c2a87e7b1f0b1a7add878c8466a6d54de5836ed285f0ec7a4fde8f2a9dcac94ebc8432992dc92632953f587ab992883c2b3b5aadcb1497ee
7
+ data.tar.gz: d597eaac6ecbaa04c6926018f3bf3872438c7138f2a64bdb52691bf2b1183c0854f34a05f5681c576a648fd69c21c90ea6395bf30c7700868dd9fecfcb332158
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- process_bot (0.1.15)
4
+ process_bot (0.1.17)
5
5
  knjrbfw (>= 0.0.116)
6
6
  pry
7
7
  rake
data/README.md CHANGED
@@ -44,6 +44,7 @@ ProcessBot provides these Sidekiq tasks:
44
44
  - `process_bot:sidekiq:stop`
45
45
  - `process_bot:sidekiq:graceful` (stops fetching new jobs and waits for running jobs by default)
46
46
  - `process_bot:sidekiq:graceful_no_wait` (stops fetching new jobs and returns immediately)
47
+ - `process_bot:sidekiq:ensure_running` (starts missing processes, including replacements for graceful shutdowns)
47
48
  - `process_bot:sidekiq:restart`
48
49
 
49
50
  You can also skip waiting for graceful completion:
@@ -70,6 +70,52 @@ namespace :process_bot do
70
70
  end
71
71
  end
72
72
 
73
+ desc "Ensure the configured number of Sidekiq ProcessBots are running (starts replacements for graceful shutdowns)"
74
+ task :ensure_running do
75
+ on roles fetch(:sidekiq_roles) do |role|
76
+ git_plugin.switch_user(role) do
77
+ desired_processes = fetch(:sidekiq_processes).to_i
78
+ running_processes = git_plugin.running_process_bot_processes
79
+
80
+ graceful_processes = running_processes.select do |process_bot_data|
81
+ git_plugin.sidekiq_process_graceful?(process_bot_data)
82
+ end
83
+
84
+ active_processes = running_processes - graceful_processes
85
+
86
+ active_indexes = active_processes.filter_map do |process_bot_data|
87
+ git_plugin.process_bot_sidekiq_index(process_bot_data)
88
+ end
89
+
90
+ graceful_indexes = graceful_processes.filter_map do |process_bot_data|
91
+ git_plugin.process_bot_sidekiq_index(process_bot_data)
92
+ end
93
+
94
+ if graceful_indexes.any?
95
+ puts "ProcessBot Sidekiq in graceful shutdown: #{graceful_indexes.join(", ")}"
96
+ puts "Starting replacements for graceful shutdowns to reach #{desired_processes} running processes"
97
+ end
98
+
99
+ missing_indexes = git_plugin.missing_sidekiq_indexes(desired_processes, active_indexes)
100
+ missing_count = desired_processes - active_indexes.count
101
+
102
+ if missing_count.negative?
103
+ puts "Found #{active_indexes.count} running ProcessBot Sidekiq processes; desired is #{desired_processes}"
104
+ missing_count = 0
105
+ end
106
+
107
+ if missing_indexes.any?
108
+ missing_indexes.each do |idx|
109
+ puts "Starting Sidekiq with ProcessBot #{idx} (missing)"
110
+ git_plugin.start_sidekiq(idx)
111
+ end
112
+ elsif missing_count.zero?
113
+ puts "All ProcessBot Sidekiq processes are running (#{active_indexes.count}/#{desired_processes})"
114
+ end
115
+ end
116
+ end
117
+ end
118
+
73
119
  desc "Restart Sidekiq and ProcessBot"
74
120
  task :restart do
75
121
  invoke! "process_bot:sidekiq:stop"
@@ -93,6 +93,37 @@ module ProcessBot::Capistrano::SidekiqHelpers # rubocop:disable Metrics/ModuleLe
93
93
  processes
94
94
  end
95
95
 
96
+ def process_bot_sidekiq_index(process_bot_data)
97
+ process_bot_id = process_bot_data["id"].to_s
98
+ match = process_bot_id.match(/-(\d+)\z/)
99
+ return nil unless match
100
+
101
+ match[1].to_i
102
+ end
103
+
104
+ def sidekiq_command_graceful?(command)
105
+ return false unless command
106
+
107
+ normalized_command = command.to_s.downcase
108
+ normalized_command.include?("stopping") || normalized_command.include?("quiet")
109
+ end
110
+
111
+ def sidekiq_process_graceful?(process_bot_data)
112
+ sidekiq_pid = process_bot_data["pid"]
113
+ return false unless sidekiq_pid
114
+
115
+ command = backend.capture(:ps, "-o", "command=", "-p", sidekiq_pid.to_s).strip
116
+ sidekiq_command_graceful?(command)
117
+ rescue SSHKit::Command::Failed
118
+ false
119
+ end
120
+
121
+ def missing_sidekiq_indexes(desired_processes, active_indexes)
122
+ desired = desired_processes.to_i
123
+ desired_indexes = (0...desired).to_a
124
+ desired_indexes - active_indexes
125
+ end
126
+
96
127
  def sidekiq_user(role = nil)
97
128
  if role.nil?
98
129
  fetch(:sidekiq_user)
@@ -215,5 +215,15 @@ class ProcessBot::Process::Handlers::Sidekiq
215
215
  logger.logs "Wait for no jobs and Stop sidekiq"
216
216
  wait_for_no_jobs
217
217
  stop
218
+ wait_for_sidekiq_exit
219
+ end
220
+
221
+ def wait_for_sidekiq_exit
222
+ return unless current_pid
223
+
224
+ while process_running?(current_pid)
225
+ logger.logs "Waiting for Sidekiq PID #{current_pid} to stop"
226
+ sleep 1
227
+ end
218
228
  end
219
229
  end
@@ -106,7 +106,8 @@ class ProcessBot::Process
106
106
 
107
107
  def send_control_command(command, **command_options)
108
108
  logger.logs "Sending #{command} command"
109
- client.send_command(command: command, options: options.options.merge(command_options))
109
+ response = client.send_command(command: command, options: options.options.merge(command_options))
110
+ raise "No response from ProcessBot while sending #{command}" if response == :nil
110
111
  rescue Errno::ECONNREFUSED => e
111
112
  raise e unless options[:ignore_no_process_bot]
112
113
  end
@@ -1,3 +1,3 @@
1
1
  module ProcessBot
2
- VERSION = "0.1.15".freeze
2
+ VERSION = "0.1.17".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: process_bot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.15
4
+ version: 0.1.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - kaspernj
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-01-05 00:00:00.000000000 Z
11
+ date: 2026-01-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: knjrbfw