angael 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -25,9 +25,14 @@ module Angael
25
25
  # Logger::WARN
26
26
  # Logger::INFO # Default
27
27
  # Logger::DEBUG
28
+ # :restart_after => If set, 1 worker will be restarted after this number
29
+ # of seconds. If it is nil (the default), then workers will not get
30
+ # restarted for no reason. If your workers leak memory, this can help
31
+ # reduce the problem. A graceful restart is always attempted.
28
32
  def initialize(worker_class, worker_count=1, worker_args=[], opts={})
29
33
  @workers = []
30
34
  worker_count.times { workers << worker_class.new(*worker_args) }
35
+ @restart_after = opts[:restart_after]
31
36
  @logger = opts[:logger]
32
37
  if @logger
33
38
  @log_level = opts[:log_level] || begin
@@ -56,15 +61,24 @@ module Angael
56
61
  end
57
62
  end
58
63
  end
64
+ trap("INT") do
65
+ stop!
66
+ end
67
+ trap("TERM") do
68
+ stop!
69
+ end
59
70
 
60
71
  loop do
61
- trap("INT") do
62
- stop!
72
+ if @restart_after
73
+ # Periodically restart workers, 1 at a time.
74
+ sleep @restart_after
75
+ w = next_worker_to_restart
76
+ w.stop!
77
+ w.start!
78
+ else
79
+ # Don't restart workers if nothing is wrong.
80
+ sleep 1
63
81
  end
64
- trap("TERM") do
65
- stop!
66
- end
67
- sleep 1
68
82
  end
69
83
  end
70
84
 
@@ -109,5 +123,15 @@ module Angael
109
123
  [pid, nil] # It did exit, but we don't know the exit status.
110
124
  end
111
125
  end
126
+
127
+ def next_worker_to_restart
128
+ @worker_count ||= workers.size
129
+ @next_worker_to_restart_index ||= 0
130
+ @next_worker_to_restart_index += 1
131
+ @next_worker_to_restart_index %= @worker_count
132
+
133
+ workers[@next_worker_to_restart_index]
134
+ end
135
+
112
136
  end
113
137
  end
@@ -1,3 +1,3 @@
1
1
  module Angael
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -39,13 +39,47 @@ describe Angael::Manager do
39
39
  Process.wait(pid)
40
40
  end
41
41
 
42
+ context "when :restart_after is set to 0.5" do
43
+ subject { Angael::Manager.new(Angael::TestSupport::SampleWorker, 3, [], :restart_after => 0.5) }
44
+ it "should restarts workers 1 at a time, at 1 second intervals" do
45
+ subject.workers.each do |w|
46
+ w.stub(:start!) # We don't actually need the workers to fork.
47
+ end
48
+
49
+ subject.workers[0].should_receive(:stop!).exactly(1).times
50
+ subject.workers[1].should_receive(:stop!).exactly(2).times # This is the worker that got restarted.
51
+ subject.workers[2].should_receive(:stop!).exactly(1).times
52
+
53
+ subject.workers[0].should_receive(:start!).exactly(1).times
54
+ subject.workers[1].should_receive(:start!).exactly(2).times # This is the worker that got restarted.
55
+ subject.workers[2].should_receive(:start!).exactly(1).times
56
+
57
+
58
+ # As an alternative to should_receive_in_child_process, we
59
+ # fork a process which will send SIGINT to this current process.
60
+ # Then we start the Manager in this process and wait for it to
61
+ # get the SIGINT. Finally we rescue SystemExit so that this
62
+ # process doesn't exit with the Manager stops.
63
+ # TODO: Be consistent in my use of this technique vs. should_receive_in_child_process.
64
+ current_pid = $$
65
+ pid = Process.fork do
66
+ sleep 0.6 # Add a 0.1 second buffer to the value of :restart_after to give the process a chance to start.
67
+ Process.kill('INT', current_pid)
68
+ exit 0
69
+ end
70
+ begin
71
+ subject.start!
72
+ rescue SystemExit
73
+ nil
74
+ end
75
+
76
+ clean_up_pid(pid)
77
+ end
78
+ end
79
+
42
80
  context "when it receives a SIGCHLD" do
43
81
  after(:each) do
44
- # Clean up
45
- unless Process.wait2(@pid, Process::WNOHANG)
46
- Process.kill('KILL', @pid) unless
47
- Process.wait(@pid) rescue nil
48
- end
82
+ clean_up_pid(@pid)
49
83
  end
50
84
 
51
85
  context "when worker was asked to stop" do
@@ -143,4 +177,11 @@ describe Angael::Manager do
143
177
  end
144
178
  end
145
179
  end
180
+
181
+ def clean_up_pid(pid)
182
+ unless Process.wait2(pid, Process::WNOHANG)
183
+ Process.kill('KILL', pid) unless
184
+ Process.wait(pid) rescue nil
185
+ end
186
+ end
146
187
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: angael
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.4
5
+ version: 0.0.5
6
6
  platform: ruby
7
7
  authors:
8
8
  - Paul Cortens
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-06-08 00:00:00 -07:00
13
+ date: 2011-06-14 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency