sv 0.0.5 → 0.0.7

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: fc419ac67937b89b2a0519205e4b38b6346d73b5
4
- data.tar.gz: 29b88973f788938d4410b970778806da8b9fe7a7
3
+ metadata.gz: b81e4dd77f7397174e6174b60951b0a8e68321cb
4
+ data.tar.gz: 6768356a525a8bf86795273a333f0a9556043d4b
5
5
  SHA512:
6
- metadata.gz: 7622979c1a4afe44cded6315fda8f98c9368e98779edb7776b2c6e13c4bc9d50697fd07fff902b0bb623d9beee65917db38914416f01a1b22f2431ae7f3dcfdc
7
- data.tar.gz: b661919407a5a9f97a22bf1ce23cc79cc2073008206f187e9b4b694ef9ab7efb4c941462ffd71e5a8de529d22b41f4ea195251967f9623e293fae1bb095876de
6
+ metadata.gz: fb03843e3d1c9bcecf7c4696fd21a9964bc87d5548567159da34b54eafcd69693438f797453c45eb91fb10b65eaeec1b127bfd0ce6b0b53ba344f0e7c8edaede
7
+ data.tar.gz: 3c1d508297b1b5b1893c599e2f07371fc698455e6d70af407830be2d9313b189b8cdfe4e57c18899e3608df2b7f28af7c86ddcae5821507da2658dd01014f11b
data/examples/jobs.yml ADDED
@@ -0,0 +1,4 @@
1
+ - name: resque
2
+ command: tail -f log/production.log
3
+ env: RAILS_ENV=production, QUEUE='*'
4
+ startsecs: 1
data/examples/sv.rb ADDED
@@ -0,0 +1,3 @@
1
+ instances ({
2
+ resque: 4
3
+ })
data/lib/sv/api.rb CHANGED
@@ -27,12 +27,25 @@ module Sv
27
27
  end
28
28
 
29
29
  def stop_job(group, name)
30
- call "supervisor.stopProcess" if not job_stopped?(group, name)
30
+ call "supervisor.stopProcess", "#{group}:#{name}" if not job_stopped?(group, name)
31
31
  rescue XMLRPC::FaultException => e
32
32
  return true if e.faultString == "NOT_RUNNING"
33
33
  raise e
34
34
  end
35
35
 
36
+ def remove_group(name)
37
+ call "supervisor.stopProcessGroup", name
38
+ call "supervisor.removeProcessGroup", name
39
+ end
40
+
41
+ def add_group(name)
42
+ ok, output = call_safe("supervisor.addProcessGroup", name)
43
+ if not ok
44
+ msg = "adding group #{name} failed: #{output.faultString}"
45
+ raise Error, msg if not output.faultString =~ /\AALREADY_ADDED/
46
+ end
47
+ end
48
+
36
49
  def job_stopped?(group, name)
37
50
  job = call "supervisor.getProcessInfo", "#{group}:#{name}"
38
51
  job["state"] == 0 ? true : false
@@ -45,7 +58,7 @@ module Sv
45
58
  def print_status
46
59
  puts "pid #{pid}"
47
60
  jobs = self.jobs
48
- name_width = jobs.map { |j| j.name.size }.max
61
+ name_width = jobs.map { |j| j.name.size }.max || 20
49
62
  template = "%-#{name_width}s %-10s %-7s %-20s\n"
50
63
  printf template, "name", "state", "pid", "uptime"
51
64
  puts "-"*(name_width + 10 + 7 + 20 + 2)
@@ -72,10 +85,31 @@ module Sv
72
85
  jobs = jobs_array.map { |j| OpenStruct.new(j) }
73
86
  end
74
87
 
88
+ def reread_config
89
+ call "supervisor.reloadConfig"
90
+ end
91
+
75
92
  def close_connection
76
93
  @rpc = nil
77
94
  end
78
95
 
96
+ def reopen_logs
97
+ Process.kill("USR2", pid)
98
+ rescue => e
99
+ raise Error, "unable to reopen logs"
100
+ end
101
+
102
+ def health_check
103
+ jobs = self.jobs
104
+ not_running_jobs = jobs.reject { |j| ["RUNNING", "STARTING"].include? j.statename }
105
+ if not_running_jobs.size > 0
106
+ names = not_running_jobs.map { |j| j.name }
107
+ str = names[0..4].join(", ")
108
+ msg = "jobs not running: #{str}"
109
+ raise Error, msg
110
+ end
111
+ puts "OK"
112
+ end
79
113
 
80
114
  private
81
115
 
@@ -92,6 +126,10 @@ module Sv
92
126
  raise ::Sv::Error, "error running command #{args[0]}"
93
127
  end
94
128
 
129
+ def call_safe(*args)
130
+ rpc.call2(*args)
131
+ end
132
+
95
133
  def uptime(started_at)
96
134
  return "-" if started_at.to_i == 0
97
135
  uptime = (Time.now.to_i - started_at).to_i
data/lib/sv/cli/server.rb CHANGED
@@ -19,7 +19,9 @@ module Sv::Cli
19
19
  server.send command, auto_start: options[:auto_start], wait: options[:wait]
20
20
  when :'print-config'
21
21
  server.send :print_config
22
- when :stop, :status
22
+ when :rr
23
+ server.send :rolling_restart
24
+ when :stop, :status, :reopen_logs, :health_check
23
25
  server.send command
24
26
  when :help
25
27
  help argv.shift
data/lib/sv/config.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'sv/logger'
2
2
  require 'sv/error'
3
3
  require 'sv/job'
4
+ require 'securerandom'
4
5
 
5
6
  module Sv
6
7
  class Config
@@ -12,6 +13,7 @@ module Sv
12
13
  @app_dir = app_dir
13
14
  @instances = {}
14
15
  @working_dir = app_dir
16
+ @namespace = SecureRandom.hex(3)
15
17
  end
16
18
 
17
19
  def socket_path
@@ -60,6 +62,7 @@ module Sv
60
62
  read_config("#{app_dir}/config/sv.rb")
61
63
  set_instances
62
64
  set_working_dir
65
+ set_namespace
63
66
  end
64
67
 
65
68
 
@@ -75,6 +78,12 @@ module Sv
75
78
  end
76
79
  end
77
80
 
81
+ def set_namespace
82
+ jobs_map.each do |name, job|
83
+ job.namespace = @namespace
84
+ end
85
+ end
86
+
78
87
  def read_config(path, optional: false)
79
88
  if not File.readable? path
80
89
  raise ::Sv::Error, "config file #{path} missing" if not optional
@@ -17,7 +17,7 @@ module Sv
17
17
  when "WARN"
18
18
  "#{severity.downcase.bold.yellow} #{msg}\n"
19
19
  else
20
- "#{severity.downcase.bold.blue} #{msg}\n"
20
+ "#{severity[0].upcase.bold.blue} #{msg}\n"
21
21
  end
22
22
  end
23
23
 
data/lib/sv/job.rb CHANGED
@@ -2,7 +2,7 @@ module Sv
2
2
  class Job
3
3
 
4
4
  attr_reader :name
5
- attr_writer :working_dir
5
+ attr_writer :working_dir, :namespace
6
6
 
7
7
  def initialize(name)
8
8
  set :name, name
@@ -12,6 +12,10 @@ module Sv
12
12
  attributes.fetch :name
13
13
  end
14
14
 
15
+ def group
16
+ @namespace ? "#{name}.#{@namespace}" : name
17
+ end
18
+
15
19
  def command(*args)
16
20
  set_or_get :command, args
17
21
  end
@@ -81,6 +85,18 @@ module Sv
81
85
  end
82
86
  end
83
87
 
88
+ def processes
89
+ processes = []
90
+ s = Struct.new(:name, :group)
91
+ numprocs.times do |i|
92
+ process = s.new
93
+ process.name = "#{name}_#{i.to_s.rjust(2,"0")}"
94
+ process.group = group
95
+ processes << process
96
+ end
97
+ processes
98
+ end
99
+
84
100
  private
85
101
 
86
102
  def attributes
@@ -124,16 +140,16 @@ module Sv
124
140
  end
125
141
  end
126
142
 
127
-
128
143
  def template
129
144
  @template ||= Pathname.new("#{__dir__}/templates/job.erb")
130
145
  end
131
146
 
132
147
  def binding
133
148
  attrs = OpenStruct.new(attributes)
149
+ attrs.group = group
134
150
  attrs.instance_eval { binding }
135
151
  end
136
-
152
+
137
153
  end
138
154
  end
139
155
 
@@ -0,0 +1,82 @@
1
+ require 'sv/logger'
2
+ module Sv
3
+ class RollingRestart
4
+
5
+ include Logger
6
+
7
+ def initialize(jobs, api)
8
+ @jobs = jobs
9
+ @api = api
10
+ end
11
+
12
+ def run
13
+ init
14
+ @api.reread_config
15
+ stop_unneeded_processes
16
+ add_new_groups
17
+ replace_processes
18
+ remove_old_groups
19
+ end
20
+
21
+ def stop_unneeded_processes
22
+ unneeded_processes.each do |x|
23
+ logger.info "#{"-".bold.red} #{x.name}: #{x.group}"
24
+ @api.stop_job x.group, x.name
25
+ end
26
+ end
27
+
28
+ def add_new_groups
29
+ @new_groups.each { |g| @api.add_group g }
30
+ end
31
+
32
+ def replace_processes
33
+ @new_processes.each do |x|
34
+ old = @old_processes.find { |p| p.name == x.name }
35
+ if old
36
+ logger.debug "stopping #{old.group}:#{old.name}"
37
+ @api.stop_job old.group, old.name
38
+ logger.info "#{"\u2219".bold.blue} #{x.name}: #{old.group} -> #{x.group}"
39
+ else
40
+ logger.info "#{"+".bold.green} #{x.name}: #{x.group}"
41
+ end
42
+ @api.start_job x.group, x.name
43
+ end
44
+ end
45
+
46
+ def remove_old_groups
47
+ @old_groups.each { |g| @api.remove_group g }
48
+ end
49
+
50
+ def unneeded_processes
51
+ @old_processes.reject { |p| @new_processes.find {|n| n.name == p.name }}
52
+ end
53
+
54
+ def load_old_processes
55
+ @old_processes = @api.jobs
56
+ end
57
+
58
+ def load_old_groups
59
+ @old_groups = @old_processes.map { |p| p.group }.uniq
60
+ end
61
+
62
+ def load_new_processes
63
+ @new_processes = []
64
+ @jobs.each do |j|
65
+ j.processes.each { |p| @new_processes << p }
66
+ end
67
+ return @new_processes
68
+ end
69
+
70
+ def load_new_groups
71
+ @new_groups = @new_processes.map { |p| p.group }.uniq
72
+ end
73
+
74
+ def init
75
+ load_new_processes
76
+ load_new_groups
77
+ load_old_processes
78
+ load_old_groups
79
+ end
80
+
81
+ end
82
+ end
data/lib/sv/server.rb CHANGED
@@ -2,6 +2,7 @@ require 'sv/config'
2
2
  require 'sv/api'
3
3
  require 'sv/supervisor/config'
4
4
  require 'sv/status'
5
+ require 'sv/rolling_restart'
5
6
 
6
7
  module Sv
7
8
  class Server
@@ -39,6 +40,27 @@ module Sv
39
40
  start auto_start: auto_start, wait: wait
40
41
  end
41
42
 
43
+ def rolling_restart
44
+ init_once
45
+ if not server_status.running?
46
+ start auto_start: true, wait: true
47
+ return
48
+ end
49
+ supervisor_config.generated_path
50
+ rolling_restart = RollingRestart.new(config.jobs, api)
51
+ rolling_restart.run
52
+ end
53
+
54
+ def reopen_logs
55
+ return if not server_status.running?
56
+ api.reopen_logs
57
+ end
58
+
59
+ def health_check
60
+ raise Error, "server not running" if not server_status.running?
61
+ api.health_check
62
+ end
63
+
42
64
  def start_jobs
43
65
  api.start_jobs
44
66
  puts api.errors
@@ -1,5 +1,5 @@
1
- [program:<%= name %>]
2
- process_name=%(program_name)s_%(process_num)02d
1
+ [program:<%= group %>]
2
+ process_name=<%= name %>_%(process_num)02d
3
3
  command=<%= command %>
4
4
  directory=<%= working_dir %>
5
5
  numprocs=<%= numprocs %>
data/lib/sv/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Sv
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.7"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neeraj
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-17 00:00:00.000000000 Z
11
+ date: 2015-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,8 @@ files:
52
52
  - README.md
53
53
  - Rakefile
54
54
  - bin/sv
55
+ - examples/jobs.yml
56
+ - examples/sv.rb
55
57
  - lib/sv.rb
56
58
  - lib/sv/api.rb
57
59
  - lib/sv/base.rb
@@ -63,6 +65,7 @@ files:
63
65
  - lib/sv/ext/string.rb
64
66
  - lib/sv/job.rb
65
67
  - lib/sv/logger.rb
68
+ - lib/sv/rolling_restart.rb
66
69
  - lib/sv/server.rb
67
70
  - lib/sv/status.rb
68
71
  - lib/sv/supervisor/config.rb