just_one_lock 0.0.2 → 0.0.3

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: 4555943b102ddd4bac3f2c732d54194126999e29
4
- data.tar.gz: 56f6671b415251bb76ee48aa37b68155dcf2bfc4
3
+ metadata.gz: ef790c43dd30dabc1e75e662d8e042ff0a49c08f
4
+ data.tar.gz: 77ef1490b78280b803160512b96beaa8aeea376f
5
5
  SHA512:
6
- metadata.gz: 991fdcbbc3634896fb0e83a68f51fe7ffa24c90b124894a3977b5ee6779d5b76efdb3ebbd2dcce7f06a4e5a27c178ce8b973940cad8aadbf824806d6716921ab
7
- data.tar.gz: 77d27fdd32f70e77a11b3ff915d9b3ee8fcd064505fac4ab7a968d9829529825b000bc6352788aeefc53956edff10f77c8ea038e89eac3e36f399d6022427c82
6
+ metadata.gz: 7f33614e6f935dfbb3040e64f09590342988ebe8566ebaca24c315d180bd73040723d165f9ede1c1804fedde2285c4d9b257ac9924ddbc84ae5d2cf94db8f477
7
+ data.tar.gz: 68a3d589c4545bdcba5e5467861d8120687e69b1b7438e6b0c5f6b86f7f0854d3674c68236f824da86e7e9f60c1151dad914100ff510beb5e275b20ea1209ee8
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  *.swp
2
2
  tags
3
+ *.gem
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- just_one_lock (0.0.1)
4
+ just_one_lock (0.0.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/lib/just_one_lock.rb CHANGED
@@ -1,33 +1,36 @@
1
1
  require 'just_one_lock/version'
2
- require 'timeout'
2
+ require 'just_one_lock/blocking'
3
+ require 'just_one_lock/non_blocking'
3
4
 
4
5
  module JustOneLock
5
- DEFAULT_TIMEOUT = 0.01
6
- class AlreadyLocked < StandardError; end
7
-
8
6
  class NullStream
9
7
  class << self
10
8
  def puts(str); end
11
- def <<(o); self; end
12
9
  end
13
10
  end
14
11
 
15
- def self.filelock(lockname, timeout: JustOneLock::DEFAULT_TIMEOUT, &block)
16
- File.open(lockname, File::RDWR|File::CREAT, 0644) do |file|
17
- Timeout::timeout(timeout, JustOneLock::AlreadyLocked) { file.flock(File::LOCK_EX) }
12
+ @files = {}
18
13
 
19
- yield
14
+ def self.delete_unlocked_files
15
+ @files.each do |path, f|
16
+ if File.exists?(path) && f.closed?
17
+ File.delete(path) rescue nil
18
+ end
20
19
  end
21
20
  end
22
21
 
23
- def self.prevent_multiple_executions(lock_dir, scope, output: JustOneLock::NullStream, timeout: JustOneLock::DEFAULT_TIMEOUT, &block)
24
- scope_name = scope.gsub(':', '_')
25
- lock_path = File.join(lock_dir, scope_name + '.lock')
22
+ private
26
23
 
27
- begin
28
- return filelock(lock_path, timeout: timeout, &block)
29
- rescue JustOneLock::AlreadyLocked => e
30
- output.puts "Another process <#{scope}> already is running"
31
- end
24
+ def self.write_pid(f)
25
+ f.rewind
26
+ f.write(Process.pid)
27
+ f.flush
28
+ f.truncate(f.pos)
29
+ end
30
+
31
+ def self.run(f, lockname, &block)
32
+ @files[lockname] = f
33
+ write_pid(f)
34
+ block.call
32
35
  end
33
36
  end
@@ -0,0 +1,42 @@
1
+ require 'timeout'
2
+
3
+ module JustOneLock::Blocking
4
+ DEFAULT_TIMEOUT = 1
5
+ class AlreadyLocked < StandardError; end
6
+
7
+ def self.filelock(
8
+ lockname,
9
+ timeout: JustOneLock::Blocking::DEFAULT_TIMEOUT,
10
+ delete_files: true,
11
+ &block
12
+ )
13
+ result = nil
14
+ File.open(lockname, File::RDWR|File::CREAT, 0644) do |f|
15
+ Timeout::timeout(timeout, JustOneLock::Blocking::AlreadyLocked) { f.flock(File::LOCK_EX) }
16
+
17
+ result = JustOneLock.run(f, lockname, &block)
18
+ end
19
+
20
+ JustOneLock.delete_unlocked_files if delete_files
21
+ result
22
+ end
23
+
24
+ def self.prevent_multiple_executions(
25
+ lock_dir,
26
+ scope,
27
+ output: JustOneLock::NullStream,
28
+ timeout: JustOneLock::Blocking::DEFAULT_TIMEOUT,
29
+ delete_files: true,
30
+ &block
31
+ )
32
+ scope_name = scope.gsub(':', '_')
33
+ lock_path = File.join(lock_dir, scope_name + '.lock')
34
+
35
+ begin
36
+ return filelock(lock_path, timeout: timeout, delete_files: delete_files, &block)
37
+ rescue JustOneLock::Blocking::AlreadyLocked => e
38
+ output.puts "Another process <#{scope}> already is running"
39
+ end
40
+ end
41
+ end
42
+
@@ -0,0 +1,37 @@
1
+ module JustOneLock::NonBlocking
2
+ def self.filelock(
3
+ lockname,
4
+ delete_files: true,
5
+ &block
6
+ )
7
+ result = nil
8
+
9
+ File.open(lockname, File::RDWR|File::CREAT, 0644) do |f|
10
+ if f.flock(File::LOCK_NB|File::LOCK_EX)
11
+ result = JustOneLock.run(f, lockname, &block)
12
+ end
13
+ end
14
+
15
+ JustOneLock.delete_unlocked_files if delete_files
16
+ result
17
+ end
18
+
19
+
20
+ def self.prevent_multiple_executions(
21
+ lock_dir,
22
+ scope,
23
+ output: JustOneLock::NullStream,
24
+ &block
25
+ )
26
+ scope_name = scope.gsub(':', '_')
27
+ lock_path = File.join(lock_dir, scope_name + '.lock')
28
+
29
+ was_executed = filelock(lock_path, &block)
30
+
31
+ unless was_executed
32
+ output.puts "Another process <#{scope}> already is running"
33
+ end
34
+ end
35
+ end
36
+
37
+
@@ -1,3 +1,3 @@
1
1
  module JustOneLock
2
- VERSION = "0.0.2"
2
+ VERSION = '0.0.3'
3
3
  end
@@ -0,0 +1,80 @@
1
+ require 'just_one_lock'
2
+ require 'tempfile'
3
+ require 'timeout'
4
+ require 'just_one_lock/locking_object'
5
+
6
+ describe JustOneLock::Blocking do
7
+ it_behaves_like 'a locking object'
8
+
9
+ def parallel(n = 2, lockpath: Tempfile.new(['sample', '.lock']).path, timeout: JustOneLock::Blocking::DEFAULT_TIMEOUT, &block)
10
+ Timeout::timeout(5) do
11
+ dir, scope = dir_and_scope(lockpath)
12
+ (1..n).map do
13
+ Thread.new do
14
+ JustOneLock::Blocking.prevent_multiple_executions(dir, scope, timeout: timeout, delete_files: false, &block)
15
+ end
16
+ end.map(&:join)
17
+ end
18
+
19
+ JustOneLock.delete_unlocked_files
20
+ end
21
+
22
+ def parallel_forks(n = 2, lockpath: Tempfile.new(['sample', '.lock']).path, timeout: JustOneLock::Blocking::DEFAULT_TIMEOUT, &block)
23
+ Timeout::timeout(5) do
24
+ dir, scope = dir_and_scope(lockpath)
25
+
26
+ (1..n).map do
27
+ fork {
28
+ JustOneLock::Blocking.prevent_multiple_executions(dir, scope, timeout: timeout, delete_files: false, &block)
29
+ }
30
+ end.map do |pid|
31
+ Process.waitpid(pid)
32
+ end
33
+ end
34
+
35
+ JustOneLock.delete_unlocked_files
36
+ end
37
+
38
+ # Java doesn't support forking
39
+ if RUBY_PLATFORM != 'java'
40
+ it 'should work for multiple processes' do
41
+ write('/tmp/number.txt', '0')
42
+
43
+ parallel_forks(6, timeout: 10) do
44
+ number = File.read('/tmp/number.txt').to_i
45
+ sleep(JustOneLock::Blocking::DEFAULT_TIMEOUT / 100)
46
+ write('/tmp/number.txt', (number + 7).to_s)
47
+ end
48
+
49
+ number = File.read('/tmp/number.txt').to_i
50
+
51
+ expect(number).to eq(42)
52
+ end
53
+
54
+ it 'should handle heavy forking' do
55
+ write('/tmp/number.txt', '0')
56
+
57
+ FORKS_NUMBER = 100
58
+ parallel_forks(FORKS_NUMBER, timeout: 10) do
59
+ number = File.read('/tmp/number.txt').to_i
60
+ write('/tmp/number.txt', (number + 1).to_s)
61
+ end
62
+
63
+ number = File.read('/tmp/number.txt').to_i
64
+
65
+ expect(number).to eq(FORKS_NUMBER)
66
+ end
67
+
68
+ it 'handles high amount of concurrent tasks' do
69
+ answer = 0
70
+
71
+ parallel(100, timeout: JustOneLock::Blocking::DEFAULT_TIMEOUT * 10) do
72
+ value = answer
73
+ answer = value + 1
74
+ end
75
+
76
+ expect(answer).to eq(100)
77
+ end
78
+ end
79
+ end
80
+
@@ -0,0 +1,168 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples 'a locking object' do
4
+ it 'runs simple ruby block as usual' do
5
+ Dir.mktmpdir do |lock_dir|
6
+ lockpath = File.join(lock_dir, 'sample.lock')
7
+ answer = 0
8
+
9
+ JustOneLock::Blocking.filelock lockpath do
10
+ answer += 42
11
+ end
12
+
13
+ expect(answer).to eq(42)
14
+ end
15
+ end
16
+
17
+ it 'returns value returned by block' do
18
+ Dir.mktmpdir do |lock_dir|
19
+ lockpath = File.join(lock_dir, 'sample.lock')
20
+ answer = 0
21
+
22
+ answer = JustOneLock::Blocking.filelock lockpath do
23
+ 42
24
+ end
25
+
26
+ expect(answer).to eq(42)
27
+ end
28
+ end
29
+
30
+ it 'runs in parallel without race condition' do
31
+ answer = 0
32
+
33
+ parallel(2) do
34
+ value = answer
35
+ sleep(JustOneLock::Blocking::DEFAULT_TIMEOUT / 2)
36
+ answer = value + 21
37
+ end
38
+
39
+ expect(answer).to eq(42)
40
+ end
41
+
42
+ it 'creates lock file on disk during block execution' do
43
+ lockpath = Tempfile.new(['sample', '.lock']).path
44
+ parallel(2, lockpath: lockpath) do
45
+ expect(File.exist?(lockpath)).to eq(true)
46
+ end
47
+ end
48
+
49
+ it 'runs in parallel without race condition' do
50
+ lockpath = Tempfile.new(['sample', '.lock']).path
51
+
52
+ answer = 0
53
+
54
+ begin
55
+ JustOneLock::Blocking.filelock(lockpath) do
56
+ raise '42'
57
+ end
58
+ rescue RuntimeError
59
+ end
60
+
61
+ JustOneLock::Blocking.filelock(lockpath) do
62
+ answer += 42
63
+ end
64
+
65
+ expect(answer).to eq(42)
66
+ end
67
+
68
+ it 'times out after specified number of seconds' do
69
+ Dir.mktmpdir do |lock_dir|
70
+ lockpath = File.join(lock_dir, 'sample.lock')
71
+
72
+ answer = 42
73
+ locked = false
74
+
75
+ Thread.new do
76
+ JustOneLock::Blocking.filelock lockpath do
77
+ locked = true
78
+ sleep 20
79
+ end
80
+ end
81
+
82
+ Timeout::timeout(1) do
83
+ while locked == false
84
+ sleep 0.1
85
+ end
86
+ end
87
+
88
+ expect do
89
+ JustOneLock::Blocking.filelock lockpath, timeout: 0.001 do
90
+ answer = 0
91
+ end
92
+ end.to raise_error(JustOneLock::Blocking::AlreadyLocked)
93
+
94
+ expect(answer).to eq(42)
95
+ end
96
+ end
97
+
98
+ # Java doesn't support forking
99
+ if RUBY_PLATFORM != 'java'
100
+
101
+ it 'should unblock files when killing processes' do
102
+ lockpath = Tempfile.new(['sample', '.lock']).path
103
+ dir, scope = dir_and_scope(lockpath)
104
+
105
+ pid = fork {
106
+ JustOneLock::Blocking.prevent_multiple_executions(lock_dir, scope) do
107
+ sleep 10
108
+ end
109
+ }
110
+
111
+ Timeout::timeout(1) do
112
+ while !File.exist?(lockpath)
113
+ sleep 0.1
114
+ end
115
+ end
116
+
117
+ answer = 0
118
+
119
+ thread = Thread.new {
120
+ JustOneLock::Blocking.prevent_multiple_executions(dir, scope) do
121
+ answer += 42
122
+ end
123
+ }
124
+
125
+ expect(answer).to eq(0)
126
+ Process.kill(9, pid)
127
+ thread.join
128
+
129
+ expect(answer).to eq(42)
130
+ end
131
+
132
+ it 'should handle Pathname as well as string path' do
133
+ Dir.mktmpdir do |lock_dir|
134
+ lockpath = Pathname.new(File.join(lock_dir, 'sample.lock'))
135
+
136
+ answer = 0
137
+ JustOneLock::Blocking.filelock lockpath do
138
+ answer += 42
139
+ end
140
+
141
+ expect(answer).to eq(42)
142
+ end
143
+ end
144
+ end
145
+
146
+ # It failed for 1.8.7 (cannot convert to String)
147
+ it 'works for Tempfile' do
148
+ answer = 0
149
+
150
+ JustOneLock::Blocking.filelock Tempfile.new(['sample', '.lock']) do
151
+ answer += 42
152
+ end
153
+
154
+ expect(answer).to eq(42)
155
+ end
156
+
157
+ # If implemented the wrong way lock is created elsewhere
158
+ it 'creates file with exact path provided' do
159
+ filename = "/tmp/awesome-lock-#{rand}.lock"
160
+
161
+ JustOneLock::Blocking.filelock filename, delete_files: false do
162
+ end
163
+
164
+ expect(File.exist?(filename)).to eq(true)
165
+ end
166
+ end
167
+
168
+
@@ -0,0 +1,38 @@
1
+ require 'just_one_lock'
2
+ require 'tempfile'
3
+ require 'timeout'
4
+ require 'just_one_lock/locking_object'
5
+
6
+ describe JustOneLock::NonBlocking do
7
+ it_behaves_like 'a locking object'
8
+
9
+ def parallel(n = 2, lockpath: Tempfile.new(['sample', '.lock']).path, &block)
10
+ Timeout::timeout(5) do
11
+ dir, scope = dir_and_scope(lockpath)
12
+ (1..n).map do
13
+ Thread.new do
14
+ JustOneLock::Blocking.prevent_multiple_executions(dir, scope, delete_files: false, &block)
15
+ end
16
+ end.map(&:join)
17
+ end
18
+
19
+ JustOneLock.delete_unlocked_files
20
+ end
21
+
22
+ def parallel_forks(n = 2, lockpath: Tempfile.new(['sample', '.lock']).path, &block)
23
+ Timeout::timeout(5) do
24
+ dir, scope = dir_and_scope(lockpath)
25
+
26
+ (1..n).map do
27
+ fork {
28
+ JustOneLock::Blocking.prevent_multiple_executions(dir, scope, delete_files: false, &block)
29
+ }
30
+ end.map do |pid|
31
+ Process.waitpid(pid)
32
+ end
33
+ end
34
+
35
+ JustOneLock.delete_unlocked_files
36
+ end
37
+ end
38
+
@@ -3,247 +3,4 @@ require 'tempfile'
3
3
  require 'timeout'
4
4
 
5
5
  describe JustOneLock do
6
-
7
- # Helper because File.write won't work for older Ruby
8
- def write(filename, contents)
9
- File.open(filename.to_s, 'w') { |f| f.write(contents) }
10
- end
11
-
12
- def dir_and_scope(lockpath)
13
- path_segments = lockpath.split('/')
14
- scope = path_segments.last
15
- path_segments.delete scope
16
- dir = path_segments.join('/')
17
- [dir, scope]
18
- end
19
-
20
- def parallel(n = 2, lockpath: Tempfile.new(['sample', '.lock']).path, timeout: JustOneLock::DEFAULT_TIMEOUT, &block)
21
- Timeout::timeout(5) do
22
- dir, scope = dir_and_scope(lockpath)
23
- (1..n).map do
24
- Thread.new do
25
- JustOneLock.prevent_multiple_executions(dir, scope, timeout: timeout, &block)
26
- end
27
- end.map(&:join)
28
- end
29
- end
30
-
31
- def parallel_forks(n = 2, lockpath: Tempfile.new(['sample', '.lock']).path, timeout: JustOneLock::DEFAULT_TIMEOUT, &block)
32
- Timeout::timeout(5) do
33
- dir, scope = dir_and_scope(lockpath)
34
-
35
- (1..n).map do
36
- fork {
37
- JustOneLock.prevent_multiple_executions(dir, scope, timeout: timeout, &block)
38
- }
39
- end.map do |pid|
40
- Process.waitpid(pid)
41
- end
42
- end
43
- end
44
-
45
- it 'runs simple ruby block as usual' do
46
- Dir.mktmpdir do |dir|
47
- lockpath = File.join(dir, 'sample.lock')
48
- answer = 0
49
-
50
- JustOneLock.filelock lockpath do
51
- answer += 42
52
- end
53
-
54
- expect(answer).to eq(42)
55
- end
56
- end
57
-
58
- it 'returns value returned by block' do
59
- Dir.mktmpdir do |dir|
60
- lockpath = File.join(dir, 'sample.lock')
61
- answer = 0
62
-
63
- answer = JustOneLock.filelock lockpath do
64
- 42
65
- end
66
-
67
- expect(answer).to eq(42)
68
- end
69
- end
70
-
71
- it 'runs in parallel without race condition' do
72
- answer = 0
73
-
74
- parallel(2) do
75
- value = answer
76
- sleep(JustOneLock::DEFAULT_TIMEOUT / 2)
77
- answer = value + 21
78
- end
79
-
80
- expect(answer).to eq(42)
81
- end
82
-
83
- it 'handles high amount of concurrent tasks' do
84
- answer = 0
85
-
86
- parallel(100) do
87
- value = answer
88
- answer = value + 1
89
- end
90
-
91
- expect(answer).to eq(100)
92
- end
93
-
94
- it 'creates lock file on disk during block execution' do
95
- lockpath = Tempfile.new(['sample', '.lock']).path
96
- parallel(2, lockpath: lockpath) do
97
- expect(File.exist?(lockpath)).to eq(true)
98
- end
99
- end
100
-
101
- it 'runs in parallel without race condition' do
102
- lockpath = Tempfile.new(['sample', '.lock']).path
103
-
104
- answer = 0
105
-
106
- begin
107
- JustOneLock.filelock(lockpath) do
108
- raise '42'
109
- end
110
- rescue RuntimeError
111
- end
112
-
113
- JustOneLock.filelock(lockpath) do
114
- answer += 42
115
- end
116
-
117
- expect(answer).to eq(42)
118
- end
119
-
120
- it 'times out after specified number of seconds' do
121
- Dir.mktmpdir do |dir|
122
- lockpath = File.join(dir, 'sample.lock')
123
-
124
- answer = 42
125
- locked = false
126
-
127
- Thread.new do
128
- JustOneLock.filelock lockpath do
129
- locked = true
130
- sleep 20
131
- end
132
- end
133
-
134
- Timeout::timeout(1) do
135
- while locked == false
136
- sleep 0.1
137
- end
138
- end
139
-
140
- expect do
141
- JustOneLock.filelock lockpath, timeout: 0.001 do
142
- answer = 0
143
- end
144
- end.to raise_error(JustOneLock::AlreadyLocked)
145
-
146
- expect(answer).to eq(42)
147
- end
148
- end
149
-
150
- # Java doesn't support forking
151
- if RUBY_PLATFORM != 'java'
152
-
153
- it 'should work for multiple processes' do
154
- write('/tmp/number.txt', '0')
155
-
156
- parallel_forks(6) do
157
- number = File.read('/tmp/number.txt').to_i
158
- sleep(JustOneLock::DEFAULT_TIMEOUT / 100)
159
- write('/tmp/number.txt', (number + 7).to_s)
160
- end
161
-
162
- number = File.read('/tmp/number.txt').to_i
163
-
164
- expect(number).to eq(42)
165
- end
166
-
167
- it 'should handle heavy forking' do
168
- write('/tmp/number.txt', '0')
169
-
170
- FORKS_NUMBER = 100
171
- parallel_forks(FORKS_NUMBER, timeout: 1) do
172
- number = File.read('/tmp/number.txt').to_i
173
- write('/tmp/number.txt', (number + 1).to_s)
174
- end
175
-
176
- number = File.read('/tmp/number.txt').to_i
177
-
178
- expect(number).to eq(FORKS_NUMBER)
179
- end
180
-
181
- it 'should unblock files when killing processes' do
182
- lockpath = Tempfile.new(['sample', '.lock']).path
183
- dir, scope = dir_and_scope(lockpath)
184
-
185
- Dir.mktmpdir do |dir|
186
- pid = fork {
187
- JustOneLock.prevent_multiple_executions(dir, scope) do
188
- sleep 10
189
- end
190
- }
191
-
192
- Timeout::timeout(1) do
193
- while !File.exist?(lockpath)
194
- sleep 0.1
195
- end
196
- end
197
-
198
- answer = 0
199
-
200
- thread = Thread.new {
201
- JustOneLock.prevent_multiple_executions(dir, scope) do
202
- answer += 42
203
- end
204
- }
205
-
206
- expect(answer).to eq(0)
207
- Process.kill(9, pid)
208
- thread.join
209
-
210
- expect(answer).to eq(42)
211
- end
212
- end
213
-
214
- it 'should handle Pathname as well as string path' do
215
- Dir.mktmpdir do |dir|
216
- lockpath = Pathname.new(File.join(dir, 'sample.lock'))
217
-
218
- answer = 0
219
- JustOneLock.filelock lockpath do
220
- answer += 42
221
- end
222
-
223
- expect(answer).to eq(42)
224
- end
225
- end
226
-
227
- end
228
-
229
- # It failed for 1.8.7 (cannot convert to String)
230
- it 'works for Tempfile' do
231
- answer = 0
232
-
233
- JustOneLock.filelock Tempfile.new(['sample', '.lock']) do
234
- answer += 42
235
- end
236
-
237
- expect(answer).to eq(42)
238
- end
239
-
240
- # If implemented the wrong way lock is created elsewhere
241
- it 'creates file with exact path provided' do
242
- filename = "/tmp/awesome-lock-#{rand}.lock"
243
-
244
- JustOneLock.filelock filename do
245
- end
246
-
247
- expect(File.exist?(filename)).to eq(true)
248
- end
249
6
  end
@@ -0,0 +1,16 @@
1
+ def lock_dir
2
+ '/tmp'
3
+ end
4
+
5
+ # Helper because File.write won't work for older Ruby
6
+ def write(filename, contents)
7
+ File.open(filename.to_s, 'w') { |f| f.write(contents) }
8
+ end
9
+
10
+ def dir_and_scope(lockpath)
11
+ path_segments = lockpath.split('/')
12
+ scope = path_segments.last
13
+ path_segments.delete scope
14
+ dir = path_segments.join('/')
15
+ [dir, scope]
16
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: just_one_lock
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Stankiewicz, Yury Kotov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-28 00:00:00.000000000 Z
11
+ date: 2014-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -69,8 +69,14 @@ files:
69
69
  - Rakefile
70
70
  - just_one_lock.gemspec
71
71
  - lib/just_one_lock.rb
72
+ - lib/just_one_lock/blocking.rb
73
+ - lib/just_one_lock/non_blocking.rb
72
74
  - lib/just_one_lock/version.rb
75
+ - spec/just_one_lock/blocking_spec.rb
76
+ - spec/just_one_lock/locking_object.rb
77
+ - spec/just_one_lock/non_blocking_spec.rb
73
78
  - spec/just_one_lock_spec.rb
79
+ - spec/spec_helper.rb
74
80
  homepage: http://github.com/beorc/just_one_lock
75
81
  licenses:
76
82
  - MIT
@@ -96,4 +102,8 @@ signing_key:
96
102
  specification_version: 4
97
103
  summary: Simple solution to prevent multiple executions using flock
98
104
  test_files:
105
+ - spec/just_one_lock/blocking_spec.rb
106
+ - spec/just_one_lock/locking_object.rb
107
+ - spec/just_one_lock/non_blocking_spec.rb
99
108
  - spec/just_one_lock_spec.rb
109
+ - spec/spec_helper.rb