singleton_process 0.0.1 → 0.0.2
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.
- data/.travis.yml +10 -0
- data/lib/singleton_process.rb +7 -7
- data/singleton_process.gemspec +2 -1
- data/spec/singleton_process_spec.rb +43 -27
- metadata +36 -20
- data/lib/singleton_process/version.rb +0 -3
data/.travis.yml
ADDED
data/lib/singleton_process.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
require "singleton_process/version"
|
2
|
-
|
3
1
|
require 'pathname'
|
4
2
|
|
5
3
|
class SingletonProcess
|
6
4
|
class AlreadyRunningError < RuntimeError; end
|
7
5
|
|
6
|
+
VERSION = '0.0.2'
|
7
|
+
|
8
8
|
attr_accessor :name, :root_path, :app_name
|
9
9
|
private :name=
|
10
10
|
|
@@ -46,15 +46,15 @@ class SingletonProcess
|
|
46
46
|
|
47
47
|
def running?
|
48
48
|
if pidfile_path.exist?
|
49
|
-
|
50
|
-
!
|
49
|
+
local_pidfile = pidfile_path.open('a')
|
50
|
+
!local_pidfile.flock(File::LOCK_EX | File::LOCK_NB)
|
51
51
|
else
|
52
52
|
false
|
53
53
|
end
|
54
54
|
ensure
|
55
|
-
if
|
56
|
-
|
57
|
-
|
55
|
+
if local_pidfile
|
56
|
+
local_pidfile.flock(File::LOCK_UN)
|
57
|
+
local_pidfile.close
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
data/singleton_process.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'singleton_process
|
4
|
+
require 'singleton_process'
|
5
5
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
7
|
gem.name = "singleton_process"
|
@@ -18,4 +18,5 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
20
|
gem.add_development_dependency 'rspec', '~>2.12.0'
|
21
|
+
gem.add_development_dependency 'childprocess', '~>0.3.8'
|
21
22
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'timeout'
|
2
|
+
require 'tempfile'
|
2
3
|
require 'spec_helper'
|
3
4
|
|
4
|
-
|
5
|
+
require File.join(File.dirname(__FILE__), '../lib/singleton_process')
|
5
6
|
|
6
7
|
describe SingletonProcess do
|
7
8
|
let(:random_pid) { rand(99999)}
|
@@ -30,12 +31,12 @@ describe SingletonProcess do
|
|
30
31
|
end
|
31
32
|
|
32
33
|
it "should accept a root_path." do
|
33
|
-
instance = described_class.new(process_name, root_path
|
34
|
+
instance = described_class.new(process_name, :root_path => tmp_pathname)
|
34
35
|
instance.root_path.should eql(tmp_pathname)
|
35
36
|
end
|
36
37
|
|
37
38
|
it "should convert root_path to a Pathname." do
|
38
|
-
instance = described_class.new(process_name, root_path
|
39
|
+
instance = described_class.new(process_name, :root_path => '/tmp')
|
39
40
|
instance.root_path.should eql(tmp_pathname)
|
40
41
|
end
|
41
42
|
|
@@ -46,7 +47,7 @@ describe SingletonProcess do
|
|
46
47
|
end
|
47
48
|
|
48
49
|
it "should accept and save an application name." do
|
49
|
-
instance = described_class.new(process_name, app_name
|
50
|
+
instance = described_class.new(process_name, :app_name => 'blah')
|
50
51
|
instance.app_name.should eql('blah')
|
51
52
|
end
|
52
53
|
end
|
@@ -60,7 +61,7 @@ describe SingletonProcess do
|
|
60
61
|
end
|
61
62
|
end
|
62
63
|
|
63
|
-
describe "lock" do
|
64
|
+
describe "#lock" do
|
64
65
|
let(:expected_error) {SingletonProcess::AlreadyRunningError}
|
65
66
|
|
66
67
|
context "when it is not already running" do
|
@@ -103,53 +104,68 @@ describe SingletonProcess do
|
|
103
104
|
]
|
104
105
|
end
|
105
106
|
|
106
|
-
|
107
|
-
|
108
|
-
|
107
|
+
let(:initial_process_output) {Tempfile.new('output')}
|
108
|
+
let(:initial_process) do
|
109
|
+
process = ChildProcess.build(*spawn_command)
|
110
|
+
process.io.stderr = process.io.stdout = initial_process_output
|
111
|
+
process
|
112
|
+
end
|
113
|
+
|
114
|
+
let(:second_process_output) {Tempfile.new('output')}
|
115
|
+
let(:second_process) do
|
116
|
+
process = ChildProcess.build(*spawn_command)
|
117
|
+
process.io.stderr = process.io.stdout = second_process_output
|
118
|
+
process
|
119
|
+
end
|
120
|
+
|
121
|
+
before :all do
|
122
|
+
require 'childprocess'
|
123
|
+
#ChildProcess.posix_spawn = true
|
109
124
|
end
|
110
125
|
|
111
126
|
after do
|
112
|
-
|
113
|
-
|
127
|
+
initial_process.stop
|
128
|
+
second_process.stop
|
129
|
+
|
130
|
+
initial_process_output.close
|
131
|
+
second_process_output.close
|
114
132
|
end
|
115
133
|
|
116
134
|
it "should raise an error." do
|
117
135
|
pidfile_path.exist?.should be_false
|
118
|
-
|
119
|
-
|
136
|
+
|
137
|
+
initial_process.start
|
120
138
|
|
121
139
|
start_time = Time.now
|
122
|
-
while Time.now - start_time <
|
140
|
+
while Time.now - start_time < 5
|
123
141
|
break if pidfile_path.exist?
|
124
142
|
sleep 0.01
|
125
143
|
end
|
126
144
|
pidfile_path.exist?.should be_true
|
127
145
|
|
128
|
-
|
129
|
-
@pid2 = wait_thr2[:pid]
|
146
|
+
second_process.start
|
130
147
|
|
131
148
|
begin
|
132
|
-
|
133
|
-
rescue
|
149
|
+
second_process.poll_for_exit(5)
|
150
|
+
rescue ChildProcess::TimeoutError
|
134
151
|
raise "Child process didn't exit properly."
|
135
152
|
end
|
136
153
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
stdin2.close; stdout2.close; stderr2.close
|
154
|
+
second_process_output.rewind
|
155
|
+
second_process_output.read.should match(/AlreadyRunningError/)
|
156
|
+
second_process.crashed?.should be_true
|
141
157
|
|
142
|
-
Process.kill(:INT,
|
158
|
+
Process.kill(:INT, initial_process.pid)
|
143
159
|
|
144
160
|
begin
|
145
|
-
|
161
|
+
initial_process.poll_for_exit(5)
|
146
162
|
rescue Timeout::Error
|
147
163
|
raise "Child process didn't exit properly."
|
148
164
|
end
|
149
165
|
|
150
|
-
|
151
|
-
|
152
|
-
|
166
|
+
initial_process_output.rewind
|
167
|
+
initial_process_output.read.should eql("#{successful_output}\n")
|
168
|
+
initial_process.exit_code.should eql(0)
|
153
169
|
end
|
154
170
|
end
|
155
171
|
end
|
@@ -184,7 +200,7 @@ describe SingletonProcess do
|
|
184
200
|
|
185
201
|
describe "#running?" do
|
186
202
|
context "when the pid file exists" do
|
187
|
-
let(:pidfile) {pidfile_path.open('
|
203
|
+
let(:pidfile) {pidfile_path.open('a')}
|
188
204
|
|
189
205
|
before do
|
190
206
|
write_random_pid
|
metadata
CHANGED
@@ -1,76 +1,92 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: singleton_process
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Robert Jackson
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
date: 2013-02-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
|
16
|
+
version_requirements: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 2.12.0
|
21
|
+
none: false
|
17
22
|
requirement: !ruby/object:Gem::Requirement
|
18
23
|
requirements:
|
19
|
-
- - ~>
|
24
|
+
- - "~>"
|
20
25
|
- !ruby/object:Gem::Version
|
21
26
|
version: 2.12.0
|
22
27
|
none: false
|
28
|
+
prerelease: false
|
23
29
|
type: :development
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: childprocess
|
24
32
|
version_requirements: !ruby/object:Gem::Requirement
|
25
33
|
requirements:
|
26
|
-
- - ~>
|
34
|
+
- - "~>"
|
27
35
|
- !ruby/object:Gem::Version
|
28
|
-
version:
|
36
|
+
version: 0.3.8
|
29
37
|
none: false
|
30
|
-
|
31
|
-
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.3.8
|
43
|
+
none: false
|
44
|
+
prerelease: false
|
45
|
+
type: :development
|
46
|
+
description: Ensure that a given process is only running once. Helpful for ensure that scheduled tasks do not overlap if they run longer than the scheduled interval.
|
32
47
|
email:
|
33
48
|
- robert.w.jackson@me.com
|
34
49
|
executables: []
|
35
50
|
extensions: []
|
36
51
|
extra_rdoc_files: []
|
37
52
|
files:
|
38
|
-
- .gitignore
|
39
|
-
- .rspec
|
53
|
+
- ".gitignore"
|
54
|
+
- ".rspec"
|
55
|
+
- ".travis.yml"
|
40
56
|
- Gemfile
|
41
57
|
- LICENSE.txt
|
42
58
|
- README.md
|
43
59
|
- Rakefile
|
44
60
|
- lib/singleton_process.rb
|
45
|
-
- lib/singleton_process/version.rb
|
46
61
|
- singleton_process.gemspec
|
47
62
|
- spec/singleton_process_spec.rb
|
48
63
|
- spec/spec_helper.rb
|
49
64
|
homepage: https://github.com/rjackson/singleton_process
|
50
65
|
licenses: []
|
51
|
-
post_install_message:
|
66
|
+
post_install_message:
|
52
67
|
rdoc_options: []
|
53
68
|
require_paths:
|
54
69
|
- lib
|
55
70
|
required_ruby_version: !ruby/object:Gem::Requirement
|
56
71
|
requirements:
|
57
|
-
- -
|
72
|
+
- - ">="
|
58
73
|
- !ruby/object:Gem::Version
|
59
|
-
version:
|
74
|
+
version: !binary |-
|
75
|
+
MA==
|
60
76
|
none: false
|
61
77
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
78
|
requirements:
|
63
|
-
- -
|
79
|
+
- - ">="
|
64
80
|
- !ruby/object:Gem::Version
|
65
|
-
version:
|
81
|
+
version: !binary |-
|
82
|
+
MA==
|
66
83
|
none: false
|
67
84
|
requirements: []
|
68
|
-
rubyforge_project:
|
85
|
+
rubyforge_project:
|
69
86
|
rubygems_version: 1.8.24
|
70
|
-
signing_key:
|
87
|
+
signing_key:
|
71
88
|
specification_version: 3
|
72
89
|
summary: Ensure that a given process is only running once.
|
73
90
|
test_files:
|
74
91
|
- spec/singleton_process_spec.rb
|
75
92
|
- spec/spec_helper.rb
|
76
|
-
has_rdoc:
|