guard-puma 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changes
2
2
 
3
+ ## 0.2.0
4
+
5
+ * Switched to puma's control server. pid file was too messy.
6
+
3
7
  ## 0.1.0
4
8
 
5
9
  * Fixed pid file path. Ready for general consumption.
data/README.md CHANGED
@@ -39,11 +39,9 @@ end
39
39
  * `:debugger` runs the server with the debugger enabled (default `false`). Required ruby-debug gem.
40
40
  * `:timeout` waits this number of seconds when restarting the Puma server before reporting there's a problem (default `20`).
41
41
  * `:config` is the path to the Puma config file (optional)
42
- * `:pidfile`` is the path to store the pid file (optional)
43
42
  * `:bind` is URI to bind to (tcp:// and unix:// only) (optional)
44
- * `:state` is the path to store the state details (optional)
45
- * `:control` is the bind URL to use for the control server. Use 'auto' to use temp unix server (optional)
46
43
  * `:control_token` is the token to use as authentication for the control server(optional)
44
+ * `:control_port` is the port to use for the control server(optional)
47
45
  * `:threads` is the min:max number of threads to use. Defaults to 0:16 (optional)
48
46
 
49
47
  ## Contributing
@@ -19,8 +19,7 @@ Gem::Specification.new do |gem|
19
19
  gem.add_dependency "puma"
20
20
  gem.add_development_dependency "rake", "~> 0.9.2.2"
21
21
  gem.add_development_dependency "rspec", "~> 2.9.0"
22
- gem.add_development_dependency "guard-rspec", "~> 0.6.0"
22
+ gem.add_development_dependency "guard-rspec", "~> 0.7.0"
23
23
  gem.add_development_dependency "bundler", "~> 1.1.0"
24
24
  gem.add_development_dependency "fakefs"
25
- gem.add_development_dependency "mocha"
26
25
  end
@@ -21,17 +21,18 @@ module Guard
21
21
  @options = DEFAULT_OPTIONS.merge(options)
22
22
  @runner = ::Guard::PumaRunner.new(@options)
23
23
  end
24
- def start
24
+
25
+ def start
25
26
  server = options[:server] ? "#{options[:server]} and " : ""
26
- UI.info "Guard::Puma will now restart your app on port #{options[:port]} using #{server}#{options[:environment]} environment."
27
- reload if options[:start_on_start]
27
+ UI.info "Guard::Puma will now start your app on port #{options[:port]} using #{server}#{options[:environment]} environment."
28
+ runner.start if options[:start_on_start]
28
29
  end
29
30
 
30
31
  def reload
31
32
  UI.info "Restarting Puma..."
32
33
  Notifier.notify("Puma restarting on port #{options[:port]} in #{options[:environment]} environment...", :title => "Restarting Puma...", :image => :pending)
33
34
  if runner.restart
34
- UI.info "Puma restarted, pid #{runner.pid}"
35
+ UI.info "Puma restarted"
35
36
  Notifier.notify("Puma restarted on port #{options[:port]}.", :title => "Puma restarted!", :image => :success)
36
37
  else
37
38
  UI.info "Puma NOT restarted, check your log files."
@@ -41,7 +42,7 @@ def start
41
42
 
42
43
  def stop
43
44
  Notifier.notify("Until next time...", :title => "Puma shutting down.", :image => :pending)
44
- runner.stop
45
+ runner.halt
45
46
  end
46
47
 
47
48
  def run_on_change(paths)
@@ -1,58 +1,40 @@
1
- require 'fileutils'
2
- require 'tmpdir'
1
+ require 'net/http'
3
2
 
4
3
  module Guard
5
4
  class PumaRunner
6
5
 
7
6
  MAX_WAIT_COUNT = 20
8
7
 
9
- attr_reader :options
8
+ attr_reader :options, :control_url, :control_token
10
9
 
11
10
  def initialize(options)
11
+ @control_token = (options.delete(:control_token) || 'pumarules')
12
+ @control = "0.0.0.0"
13
+ @control_port = (options.delete(:control_port) || '9293')
14
+ @control_url = "#{@control}:#{@control_port}"
12
15
  @options = options
13
16
  end
14
17
 
15
18
  def start
16
- kill_unmanaged_pid! if options[:force_run]
17
- run_puma_command!
18
- wait_for_pid
19
- end
20
-
21
- def stop
22
- if File.file?(pid_file)
23
- system %{kill -KILL #{File.read(pid_file).strip}}
24
- wait_for_no_pid if $?.exitstatus == 0
25
- FileUtils.rm pid_file
26
- end
27
- end
28
-
29
- def restart
30
- stop
31
- start
32
- end
33
-
34
- def build_puma_command
35
19
  puma_options = {
36
20
  '--port' => options[:port],
37
- '--pidfile' => pid_file,
21
+ '--control-token' => @control_token,
22
+ '--control' => "tcp://#{@control_url}"
38
23
  }
39
- [:config, :bind, :state, :control, :threads].each do |opt|
24
+ [:config, :bind, :threads].each do |opt|
40
25
  puma_options["--#{opt}"] = options[opt] if options[opt]
41
26
  end
42
- puma_options["--control-token"] = options[:control_token] if options[:control_token]
43
27
  opts = puma_options.to_a.flatten << '-q'
44
28
 
45
29
  %{sh -c 'cd #{Dir.pwd} && puma #{opts.join(' ')} &'}
46
30
  end
47
31
 
48
- def pid_file
49
- pidfilepath = File.expand_path(options[:pidfile]) if options[:pidfile]
50
- @pf ||= (pidfilepath || \
51
- File.expand_path("#{Dir.tmpdir}/guard-puma-#{options[:environment]}.pid"))
32
+ def halt
33
+ run_puma_command!("halt")
52
34
  end
53
35
 
54
- def pid
55
- File.file?(pid_file) ? File.read(pid_file).to_i : nil
36
+ def restart
37
+ run_puma_command!("restart")
56
38
  end
57
39
 
58
40
  def sleep_time
@@ -61,54 +43,14 @@ module Guard
61
43
 
62
44
  private
63
45
 
64
- def run_puma_command!
65
- system build_puma_command
66
- end
67
-
68
- def has_pid?
69
- File.file?(pid_file)
70
- end
71
-
72
- def wait_for_pid_action
73
- sleep sleep_time
74
- end
75
-
76
- def kill_unmanaged_pid!
77
- if pid = unmanaged_pid
78
- system %{kill -KILL #{pid}}
79
- FileUtils.rm pid_file
80
- wait_for_no_pid
81
- end
46
+ def run_puma_command!(cmd)
47
+ Net::HTTP.get((build_uri(cmd)))
82
48
  end
83
49
 
84
- def unmanaged_pid
85
- %x{lsof -n -i TCP:#{options[:port]}}.each_line { |line|
86
- if line["*:#{options[:port]} "]
87
- return line.split("\s")[1]
88
- end
89
- }
90
- nil
50
+ def build_uri(cmd)
51
+ URI("http://#{control_url}/#{cmd}?token=#{control_token}")
91
52
  end
92
53
 
93
- private
94
-
95
- def wait_for_pid
96
- wait_for_pid_loop
97
- end
98
-
99
- def wait_for_no_pid
100
- wait_for_pid_loop(false)
101
- end
102
-
103
- def wait_for_pid_loop(check_for_existence = true)
104
- count = 0
105
- while !(check_for_existence ? has_pid? : !has_pid?) && count < MAX_WAIT_COUNT
106
- wait_for_pid_action
107
- count += 1
108
- end
109
- !(count == MAX_WAIT_COUNT)
110
- end
111
-
112
54
  end
113
55
  end
114
56
 
@@ -1,5 +1,5 @@
1
1
  module Guard
2
2
  module PumaVersion
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
@@ -1,6 +1,5 @@
1
1
  require 'spec_helper'
2
2
  require 'guard/puma/runner'
3
- require 'fakefs/spec_helpers'
4
3
 
5
4
  describe Guard::PumaRunner do
6
5
  let(:runner) { Guard::PumaRunner.new(options) }
@@ -9,80 +8,26 @@ describe Guard::PumaRunner do
9
8
 
10
9
  let(:default_options) { { :environment => environment, :port => port } }
11
10
  let(:options) { default_options }
12
-
13
- describe '#pid' do
14
- include FakeFS::SpecHelpers
15
-
16
- context 'pid file exists' do
17
- let(:pid) { 12345 }
18
-
19
- before do
20
- FileUtils.mkdir_p File.split(runner.pid_file).first
21
- File.open(runner.pid_file, 'w') { |fh| fh.print pid }
22
- end
23
11
 
24
- it "reads the pid" do
25
- runner.pid.should == pid
26
- end
27
- end
28
-
29
- context 'pid file does not exist' do
30
- it "returns nil" do
31
- if defined?(Rubinius)
32
- runner.pid.should == nil
33
- else
34
- runner.pid.should be_nil
35
- end
36
- end
12
+ describe "#initialize" do
13
+ it "sets options" do
14
+ runner.options.should eq(options)
37
15
  end
38
16
  end
39
-
40
- describe '#start' do
41
- let(:kill_expectation) { runner.expects(:kill_unmanaged_pid!) }
42
- let(:pid_stub) { runner.stubs(:has_pid?) }
43
-
44
- before do
45
- runner.expects(:run_puma_command!).once
46
- end
47
-
48
- context 'do not force run' do
49
- before do
50
- pid_stub.returns(true)
51
- kill_expectation.never
52
- runner.expects(:wait_for_pid_action).never
53
- end
54
-
55
- it "acts properly" do
56
- runner.start.should be_true
57
- end
58
- end
59
-
60
- context 'force run' do
61
- let(:options) { default_options.merge(:force_run => true) }
62
-
63
- before do
64
- pid_stub.returns(true)
65
- kill_expectation.once
66
- runner.expects(:wait_for_pid_action).never
67
- end
68
-
69
- it "acts properly" do
70
- runner.start.should be_true
71
- end
72
- end
73
-
74
- context "don't write the pid" do
17
+
18
+ %w(halt restart).each do |cmd|
19
+ describe cmd do
75
20
  before do
76
- pid_stub.returns(false)
77
- kill_expectation.never
78
- runner.expects(:wait_for_pid_action).times(Guard::PumaRunner::MAX_WAIT_COUNT)
21
+ runner.stub(:build_uri).with(cmd).and_return(uri)
79
22
  end
80
-
81
- it "acts properly" do
82
- runner.start.should be_false
23
+ let(:uri) { URI("http://#{runner.control_url}/#{cmd}?token=#{runner.control_token}") }
24
+ it "#{cmd}s" do
25
+ Net::HTTP.should_receive(:get).with(uri).once
26
+ runner.send(cmd.intern)
83
27
  end
84
28
  end
85
29
  end
30
+
86
31
 
87
32
  describe '#sleep_time' do
88
33
  let(:timeout) { 30 }
@@ -94,9 +39,8 @@ describe Guard::PumaRunner do
94
39
  end
95
40
 
96
41
  describe "#build_puma_command" do
97
- let(:command) {
98
- Guard::PumaRunner.new(options).build_puma_command
99
- }
42
+ let(:command) { Guard::PumaRunner.new(options).start }
43
+
100
44
  context "with config" do
101
45
  let(:options) {{ :config => path }}
102
46
  let(:path) { "/tmp/elephants" }
@@ -113,22 +57,6 @@ describe Guard::PumaRunner do
113
57
  end
114
58
  end
115
59
 
116
- context "with state" do
117
- let(:options) {{ :state => path }}
118
- let(:path) { "/tmp/zebras" }
119
- it "adds path to command" do
120
- command.should match("--state #{path}")
121
- end
122
- end
123
-
124
- context "with control" do
125
- let(:options) {{ :control => uri }}
126
- let(:uri) { "http://foo" }
127
- it "adds path to command" do
128
- command.should match("--control #{uri}")
129
- end
130
- end
131
-
132
60
  context "with control_token" do
133
61
  let(:options) {{ :control_token => token }}
134
62
  let(:token) { "IMMA_TOKEN" }
@@ -15,12 +15,10 @@ describe Guard::Puma do
15
15
  end
16
16
 
17
17
  describe '#start' do
18
- let(:ui_expectation) { Guard::UI.expects(:info).with(regexp_matches(/#{Guard::Puma::DEFAULT_OPTIONS[:port]}/)) }
19
18
 
20
19
  context 'start on start' do
21
- it "shows the right message and run startup" do
22
- guard.expects(:reload).once
23
- ui_expectation
20
+ it "runs startup" do
21
+ guard.should_receive(:start).once
24
22
  guard.start
25
23
  end
26
24
  end
@@ -29,62 +27,42 @@ describe Guard::Puma do
29
27
  let(:options) { { :start_on_start => false } }
30
28
 
31
29
  it "shows the right message and not run startup" do
32
- guard.expects(:reload).never
33
- ui_expectation
30
+ guard.runner.should_receive(:start).never
34
31
  guard.start
35
32
  end
36
33
  end
37
34
  end
38
35
 
39
36
  describe '#reload' do
40
- let(:pid) { '12345' }
41
37
 
42
38
  before do
43
- Guard::UI.expects(:info).with('Restarting Puma...')
44
- Guard::Notifier.expects(:notify).with(regexp_matches(/Puma restarting/), has_entry(:image => :pending))
45
- Guard::PumaRunner.any_instance.stubs(:pid).returns(pid)
39
+ Guard::UI.should_receive(:info).with('Restarting Puma...')
40
+ Guard::Notifier.should_receive(:notify).with(/Puma restarting/, hash_including(:image => :pending))
41
+ guard.runner.stub(:restart).and_return(true)
46
42
  end
47
43
 
48
- let(:runner_stub) { Guard::PumaRunner.any_instance.stubs(:restart) }
44
+ let(:runner_stub) { Guard::PumaRunner.any_instance.stub(:halt) }
49
45
 
50
- context 'with pid file' do
51
- before do
52
- runner_stub.returns(true)
53
- end
54
-
55
- it "restarts and show the pid file" do
56
- Guard::UI.expects(:info).with(regexp_matches(/#{pid}/))
57
- Guard::Notifier.expects(:notify).with(regexp_matches(/Puma restarted/), has_entry(:image => :success))
46
+ it "restarts and show the message" do
47
+ Guard::UI.should_receive(:info)
48
+ Guard::Notifier.should_receive(:notify).with(/Puma restarted/, hash_including(:image => :success))
58
49
 
59
- guard.reload
60
- end
50
+ guard.reload
61
51
  end
62
52
 
63
- context 'no pid file' do
64
- before do
65
- runner_stub.returns(false)
66
- end
67
-
68
- it "restarts and show the pid file" do
69
- Guard::UI.expects(:info).with(regexp_matches(/#{pid}/)).never
70
- Guard::UI.expects(:info).with(regexp_matches(/Puma NOT restarted/))
71
- Guard::Notifier.expects(:notify).with(regexp_matches(/Puma NOT restarted/), has_entry(:image => :failed))
72
-
73
- guard.reload
74
- end
75
- end
76
53
  end
77
54
 
78
55
  describe '#stop' do
79
56
  it "stops correctly" do
80
- Guard::Notifier.expects(:notify).with('Until next time...', anything)
57
+ Guard::Notifier.should_receive(:notify).with('Until next time...', anything)
58
+ guard.runner.should_receive(:halt).once
81
59
  guard.stop
82
60
  end
83
61
  end
84
62
 
85
63
  describe '#run_on_change' do
86
64
  it "reloads on change" do
87
- guard.expects(:reload).once
65
+ guard.should_receive(:reload).once
88
66
  guard.run_on_change([])
89
67
  end
90
68
  end
@@ -6,11 +6,10 @@
6
6
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
7
  ENV["GUARD_ENV"] = 'test'
8
8
  require 'rspec'
9
- require 'mocha'
10
9
 
11
10
  RSpec.configure do |config|
12
11
  config.treat_symbols_as_metadata_keys_with_true_values = true
13
12
  config.run_all_when_everything_filtered = true
14
13
  config.filter_run :focus
15
- config.mock_with :mocha
14
+ config.mock_with :rspec
16
15
  end
metadata CHANGED
@@ -1,176 +1,115 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: guard-puma
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
5
4
  prerelease:
5
+ version: 0.2.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Jesse Cooke
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-22 00:00:00.000000000 Z
12
+ date: 2012-04-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: guard
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: 1.0.1
22
15
  type: :runtime
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
16
+ version_requirements: &6804 !ruby/object:Gem::Requirement
26
17
  requirements:
27
18
  - - ! '>='
28
19
  - !ruby/object:Gem::Version
29
20
  version: 1.0.1
30
- - !ruby/object:Gem::Dependency
31
- name: rb-inotify
32
- requirement: !ruby/object:Gem::Requirement
33
21
  none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: '0'
38
- type: :runtime
39
22
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
23
+ name: guard
24
+ requirement: *6804
46
25
  - !ruby/object:Gem::Dependency
47
- name: libnotify
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
51
- - - ! '>='
52
- - !ruby/object:Gem::Version
53
- version: '0'
54
26
  type: :runtime
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
27
+ version_requirements: &6860 !ruby/object:Gem::Requirement
58
28
  requirements:
59
29
  - - ! '>='
60
30
  - !ruby/object:Gem::Version
61
31
  version: '0'
62
- - !ruby/object:Gem::Dependency
63
- name: puma
64
- requirement: !ruby/object:Gem::Requirement
65
32
  none: false
33
+ prerelease: false
34
+ name: rb-inotify
35
+ requirement: *6860
36
+ - !ruby/object:Gem::Dependency
37
+ type: :runtime
38
+ version_requirements: &6904 !ruby/object:Gem::Requirement
66
39
  requirements:
67
40
  - - ! '>='
68
41
  - !ruby/object:Gem::Version
69
42
  version: '0'
70
- type: :runtime
71
- prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
43
  none: false
44
+ prerelease: false
45
+ name: libnotify
46
+ requirement: *6904
47
+ - !ruby/object:Gem::Dependency
48
+ type: :runtime
49
+ version_requirements: &6948 !ruby/object:Gem::Requirement
74
50
  requirements:
75
51
  - - ! '>='
76
52
  - !ruby/object:Gem::Version
77
53
  version: '0'
78
- - !ruby/object:Gem::Dependency
79
- name: rake
80
- requirement: !ruby/object:Gem::Requirement
81
54
  none: false
82
- requirements:
83
- - - ~>
84
- - !ruby/object:Gem::Version
85
- version: 0.9.2.2
86
- type: :development
87
55
  prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
- none: false
56
+ name: puma
57
+ requirement: *6948
58
+ - !ruby/object:Gem::Dependency
59
+ type: :development
60
+ version_requirements: &6992 !ruby/object:Gem::Requirement
90
61
  requirements:
91
62
  - - ~>
92
63
  - !ruby/object:Gem::Version
93
64
  version: 0.9.2.2
94
- - !ruby/object:Gem::Dependency
95
- name: rspec
96
- requirement: !ruby/object:Gem::Requirement
97
65
  none: false
98
- requirements:
99
- - - ~>
100
- - !ruby/object:Gem::Version
101
- version: 2.9.0
102
- type: :development
103
66
  prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- none: false
67
+ name: rake
68
+ requirement: *6992
69
+ - !ruby/object:Gem::Dependency
70
+ type: :development
71
+ version_requirements: &7036 !ruby/object:Gem::Requirement
106
72
  requirements:
107
73
  - - ~>
108
74
  - !ruby/object:Gem::Version
109
75
  version: 2.9.0
110
- - !ruby/object:Gem::Dependency
111
- name: guard-rspec
112
- requirement: !ruby/object:Gem::Requirement
113
76
  none: false
114
- requirements:
115
- - - ~>
116
- - !ruby/object:Gem::Version
117
- version: 0.6.0
118
- type: :development
119
77
  prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
- requirements:
123
- - - ~>
124
- - !ruby/object:Gem::Version
125
- version: 0.6.0
78
+ name: rspec
79
+ requirement: *7036
126
80
  - !ruby/object:Gem::Dependency
127
- name: bundler
128
- requirement: !ruby/object:Gem::Requirement
129
- none: false
81
+ type: :development
82
+ version_requirements: &7080 !ruby/object:Gem::Requirement
130
83
  requirements:
131
84
  - - ~>
132
85
  - !ruby/object:Gem::Version
133
- version: 1.1.0
134
- type: :development
135
- prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
86
+ version: 0.7.0
137
87
  none: false
88
+ prerelease: false
89
+ name: guard-rspec
90
+ requirement: *7080
91
+ - !ruby/object:Gem::Dependency
92
+ type: :development
93
+ version_requirements: &7124 !ruby/object:Gem::Requirement
138
94
  requirements:
139
95
  - - ~>
140
96
  - !ruby/object:Gem::Version
141
97
  version: 1.1.0
142
- - !ruby/object:Gem::Dependency
143
- name: fakefs
144
- requirement: !ruby/object:Gem::Requirement
145
98
  none: false
146
- requirements:
147
- - - ! '>='
148
- - !ruby/object:Gem::Version
149
- version: '0'
150
- type: :development
151
99
  prerelease: false
152
- version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
- requirements:
155
- - - ! '>='
156
- - !ruby/object:Gem::Version
157
- version: '0'
100
+ name: bundler
101
+ requirement: *7124
158
102
  - !ruby/object:Gem::Dependency
159
- name: mocha
160
- requirement: !ruby/object:Gem::Requirement
161
- none: false
162
- requirements:
163
- - - ! '>='
164
- - !ruby/object:Gem::Version
165
- version: '0'
166
103
  type: :development
167
- prerelease: false
168
- version_requirements: !ruby/object:Gem::Requirement
169
- none: false
104
+ version_requirements: &7168 !ruby/object:Gem::Requirement
170
105
  requirements:
171
106
  - - ! '>='
172
107
  - !ruby/object:Gem::Version
173
108
  version: '0'
109
+ none: false
110
+ prerelease: false
111
+ name: fakefs
112
+ requirement: *7168
174
113
  description:
175
114
  email:
176
115
  - jesse@jc00ke.com
@@ -201,20 +140,20 @@ rdoc_options: []
201
140
  require_paths:
202
141
  - lib
203
142
  required_ruby_version: !ruby/object:Gem::Requirement
204
- none: false
205
143
  requirements:
206
144
  - - ! '>='
207
145
  - !ruby/object:Gem::Version
208
146
  version: '0'
209
- required_rubygems_version: !ruby/object:Gem::Requirement
210
147
  none: false
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
211
149
  requirements:
212
150
  - - ! '>='
213
151
  - !ruby/object:Gem::Version
214
152
  version: '0'
153
+ none: false
215
154
  requirements: []
216
155
  rubyforge_project:
217
- rubygems_version: 1.8.19
156
+ rubygems_version: 1.8.12
218
157
  signing_key:
219
158
  specification_version: 3
220
159
  summary: Restart puma when files change