with_lock 0.0.4.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +8 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +26 -0
- data/README.md +45 -0
- data/Rakefile +9 -0
- data/config/with_lock.local.yml +3 -0
- data/config/with_lock.yml +3 -0
- data/lib/with_lock.rb +89 -0
- data/lib/with_lock/client.rb +76 -0
- data/lib/with_lock/server.rb +119 -0
- data/lib/with_lock/version.rb +4 -0
- data/script/with_lock +37 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/support/echo_pid.sh +2 -0
- data/spec/support/get_lock.rb +21 -0
- data/spec/with_lock_spec.rb +130 -0
- data/with_lock.gemspec +23 -0
- metadata +94 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
OTIxODdiOTM5NjRiZGEwMWRmYTE3NDJiMDEyMmQ5N2NiZWNhNTRiOQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NDNkNjI2MDUxMmZhYmE3OWNmZThiOTI5NzMzNjgzOTFlOTU0NTNlMQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MDNhYTE5YTI3ZTE3ZWJhMTY4ODNlNWExNjI4YTQ2Y2ExNjM3NjVkM2M4OTk1
|
10
|
+
ODlhMmM4MTNlNzEyOGZkZjVjMzIyODcwZWNjMDc5NGRjM2MxOTlmYTFmZGE0
|
11
|
+
ZTBjNmFlOGRjZDgwZGU0MjA2NDNhZTJjZTc2MThjN2FkM2FjZWY=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NzQzMWRhZTE5YjFlZDkyODFhY2FmNzRlODdkYzcxMmQyZWFhMWI3YjgzYWI3
|
14
|
+
NThiMjNlNDExYjkzYjZmM2FiMzAyZTc0Y2M1ZjE2ZWNjMWU5NDQ5NzFmNjU3
|
15
|
+
OTFmMWY3NTZiYmRmOTgwYmFkNGFmMmU3N2Y4MzFhYzRmYmExYzY=
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
with_lock (0.0.4.alpha)
|
5
|
+
daemons
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
daemons (1.1.9)
|
11
|
+
diff-lcs (1.1.3)
|
12
|
+
rspec (2.8.0)
|
13
|
+
rspec-core (~> 2.8.0)
|
14
|
+
rspec-expectations (~> 2.8.0)
|
15
|
+
rspec-mocks (~> 2.8.0)
|
16
|
+
rspec-core (2.8.0)
|
17
|
+
rspec-expectations (2.8.0)
|
18
|
+
diff-lcs (~> 1.1.2)
|
19
|
+
rspec-mocks (2.8.0)
|
20
|
+
|
21
|
+
PLATFORMS
|
22
|
+
ruby
|
23
|
+
|
24
|
+
DEPENDENCIES
|
25
|
+
rspec
|
26
|
+
with_lock!
|
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# WithLock
|
2
|
+
|
3
|
+
Provides a DRb service to provide locking across a distributed ruby application.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add to your Gemfile and run the `bundle` command to install it.
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem "with_lock", git: 'https://github.com/chrisboy333/with_lock.git'
|
11
|
+
```
|
12
|
+
|
13
|
+
**Tested under Ruby 1.9.3.**
|
14
|
+
|
15
|
+
Add script and config files to your project(from console):
|
16
|
+
```ruby
|
17
|
+
WithLock.setup
|
18
|
+
```
|
19
|
+
In the configuration file you can change some settings if you like ... it defaults to using the following... where 'scope' is the application directory name with rails environment appended(if present):
|
20
|
+
url: druby://loclahost:9999
|
21
|
+
scope: <%= File.basename(File.expand_path('.')) %><%= ":#{Rails.env}" if defined?(Rails) %>
|
22
|
+
directory: tmp
|
23
|
+
|
24
|
+
The scope is used to let different applications use the same drb server ... or different parts of an app acquire the same named locks(not that I think this latter is a great idea) ...
|
25
|
+
|
26
|
+
Start/Stop the service from ruby
|
27
|
+
```ruby
|
28
|
+
WithLock::Server.start_service
|
29
|
+
WithLock::Server.stop_service
|
30
|
+
```
|
31
|
+
Start/Stop service from
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
A "with_lock()" function is provided globally to wrap with_lock sections of code.
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
with_lock('lock_name') do
|
38
|
+
puts "This is something only I can do right now, provided others are using the locks!"
|
39
|
+
end
|
40
|
+
```
|
41
|
+
## Development
|
42
|
+
|
43
|
+
Questions or problems? Please post them on the [issue tracker](https://github.com/chrisboy333/with_lock/issues). You can contribute changes by forking the project and submitting a pull request. You can ensure the tests passing by running `bundle` and `rake`.
|
44
|
+
|
45
|
+
This gem is created by Christopher Hauboldt and is under the MIT License.
|
data/Rakefile
ADDED
data/lib/with_lock.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require "with_lock/version"
|
2
|
+
require 'erb'
|
3
|
+
require 'yaml'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'logger'
|
6
|
+
|
7
|
+
module WithLock
|
8
|
+
class LockException < Exception
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.setup
|
12
|
+
gem_dir = File.expand_path(File.join('..','..'),__FILE__)
|
13
|
+
app_dir = File.expand_path('.')
|
14
|
+
FileUtils.cp(File.join(gem_dir,'config','with_lock.yml'),File.join(app_dir,'config','with_lock.yml'))
|
15
|
+
FileUtils.cp(File.join(gem_dir,'script','with_lock'),File.join(app_dir,'script','with_lock'))
|
16
|
+
FileUtils.chmod(0755, File.join(app_dir,'script','with_lock'))
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
module Public
|
21
|
+
def with_lock(name,timeout=5,&block)
|
22
|
+
WithLock::Client.with_lock(name,timeout) do
|
23
|
+
yield
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module Common
|
29
|
+
def logger
|
30
|
+
return @@logger if defined?(@@logger) && !@@logger.nil?
|
31
|
+
@@logger = nil
|
32
|
+
@@logger = Rails.logger if defined?(Rails)
|
33
|
+
FileUtils.mkdir_p('log') if @@logger.nil?
|
34
|
+
@@logger ||= Logger.new(File.join('log','with_lock.log'))
|
35
|
+
end
|
36
|
+
|
37
|
+
def url
|
38
|
+
settings['url']
|
39
|
+
end
|
40
|
+
|
41
|
+
def pidfile
|
42
|
+
File.join('tmp','pids','with_lock.pid')
|
43
|
+
end
|
44
|
+
|
45
|
+
def pid
|
46
|
+
File.read(pidfile).strip
|
47
|
+
rescue => e
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def running?(pid)
|
52
|
+
`ps -p#{pid} | wc -l`.to_i == 2
|
53
|
+
end
|
54
|
+
|
55
|
+
def settings_filename
|
56
|
+
File.join('config','with_lock.yml')
|
57
|
+
end
|
58
|
+
|
59
|
+
def local_settings_filename
|
60
|
+
File.join('config','with_lock.local.yml')
|
61
|
+
end
|
62
|
+
|
63
|
+
def settings
|
64
|
+
return @@settings if defined? @@settings
|
65
|
+
@@settings = default_settings
|
66
|
+
@@settings = @@settings.merge!(load_settings(settings_filename)||{}) if File.exists?(settings_filename)
|
67
|
+
@@settings.merge!(load_settings(local_settings_filename)||{}) if File.exists?(local_settings_filename)
|
68
|
+
@@settings
|
69
|
+
end
|
70
|
+
|
71
|
+
def default_settings
|
72
|
+
{
|
73
|
+
'directory' => File.join('tmp'),
|
74
|
+
'url' => "druby://localhost:9999",
|
75
|
+
'scope' => "#{File.basename(File.expand_path('.'))}#{":#{Rails.env}" if defined?(Rails)}"
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def load_settings(filename)
|
80
|
+
YAML.load(ERB.new(File.read(filename)).result)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
WithLock::Public.respond_to?(:with_lock)
|
86
|
+
|
87
|
+
require 'with_lock/server'
|
88
|
+
require 'with_lock/client'
|
89
|
+
Object.send :include, WithLock::Public
|
@@ -0,0 +1,76 @@
|
|
1
|
+
class WithLock::Client
|
2
|
+
extend WithLock::Common
|
3
|
+
@@locker = nil
|
4
|
+
|
5
|
+
def self.scoped_name(name)
|
6
|
+
"#{scope}-#{name}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.identity
|
10
|
+
"#{`hostname`.strip}|#{$$}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.get(name,timeout=5)
|
14
|
+
locker.get(identity,scoped_name(name),timeout)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.release(name)
|
18
|
+
locker.release(identity,scoped_name(name))
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.mine?(name)
|
22
|
+
locker.mine?(identity,scoped_name(name))
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.with_lock(name, timeout=5, &block)
|
26
|
+
begin
|
27
|
+
locked = mine?(name) && increment(name)
|
28
|
+
locked ||= get(name,timeout) || raise(WithLock::LockException.new("Failed to obtain lock #{name} in #{timeout} seconds."))
|
29
|
+
yield
|
30
|
+
ensure
|
31
|
+
if locker_available?
|
32
|
+
decrement(name).to_i > 0 || release(name) || logger.debug("Warning: lock #{name} not released!")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.locker_available?
|
38
|
+
locker.url
|
39
|
+
true
|
40
|
+
rescue DRb::DRbConnError => e
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.increment(name)
|
45
|
+
locker.increment(identity,scoped_name(name))
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.decrement(name)
|
49
|
+
locker.decrement(identity,scoped_name(name))
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.scope
|
53
|
+
@@scope ||= Rails.env if defined? Rails
|
54
|
+
@@scope ||= File.expand_path('.').split(File::SEPARATOR).last
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.reconnect!
|
58
|
+
DRb.stop_service
|
59
|
+
@@uri = DRb.start_service
|
60
|
+
@@locker = DRbObject.new_with_uri(url)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.locker
|
64
|
+
return @@locker if (@@locker.url rescue false)
|
65
|
+
@@locker = nil
|
66
|
+
tries = 3
|
67
|
+
while @@locker.nil? && tries > 0 do
|
68
|
+
sleep 0.2 if tries < 3
|
69
|
+
tries -= 1
|
70
|
+
reconnect!
|
71
|
+
@@locker = nil unless (@@locker.url rescue false)
|
72
|
+
end
|
73
|
+
raise WithLock::LockException.new("Couldn't connect to locker.") if @@locker.nil?
|
74
|
+
@@locker
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'drb'
|
2
|
+
require 'daemons'
|
3
|
+
|
4
|
+
class WithLock::Server
|
5
|
+
extend WithLock::Common
|
6
|
+
|
7
|
+
def self.mutex
|
8
|
+
@@mutex ||= Mutex.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.owner_uri?(name)
|
12
|
+
locks[name][:owner]
|
13
|
+
rescue => e
|
14
|
+
''
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.owner_pid(name)
|
18
|
+
locks[name][:pid]
|
19
|
+
rescue => e
|
20
|
+
''
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.count(name)
|
24
|
+
locks[name][:count]
|
25
|
+
rescue => e
|
26
|
+
0
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.locked?(name)
|
30
|
+
!locks[name].nil?# && owner_active?(name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.mine?(owner,name)
|
34
|
+
locked?(name) && locks[name][:owner].eql?(owner)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.get(owner,name,timeout=5)
|
38
|
+
endtime = Time.now.to_f + timeout.to_f
|
39
|
+
owner_uri, owner_pid = owner.split('|')
|
40
|
+
while !mine?(owner,name) && (Time.now.to_f < endtime)
|
41
|
+
mutex.synchronize do
|
42
|
+
if !locked?(name)
|
43
|
+
locks[name] = {owner: owner, count: 1}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
sleep 0.01 unless mine?(owner,name)
|
47
|
+
end
|
48
|
+
mine?(owner,name)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.release(owner,name)
|
52
|
+
if mine?(owner,name)
|
53
|
+
locks.delete(name)
|
54
|
+
true
|
55
|
+
else
|
56
|
+
false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.increment(owner,name)
|
61
|
+
if mine?(owner,name)
|
62
|
+
locks[name][:count] += 1
|
63
|
+
end
|
64
|
+
count(name)
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.decrement(owner,name)
|
68
|
+
if mine?(owner,name)
|
69
|
+
locks[name][:count] -= 1
|
70
|
+
end
|
71
|
+
count(name)
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.locks
|
75
|
+
@@locks ||= {}
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.write_url(url)
|
79
|
+
File.open(File.join(settings['directory'],'with_lock'),'w'){|file| file.write(url)}
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.started?
|
83
|
+
pid.to_i > 0 && running?(pid)
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.daemon_settings
|
87
|
+
{
|
88
|
+
:multiple => false,
|
89
|
+
:ontop => false,
|
90
|
+
:backtrace => true,
|
91
|
+
:log_output => true,
|
92
|
+
:monitor => false,
|
93
|
+
:dir_mode => :normal,
|
94
|
+
:dir => 'tmp/pids'
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.start_service
|
99
|
+
return if started?
|
100
|
+
FileUtils.rm(pidfile) if File.exists?(pidfile)
|
101
|
+
options = daemon_settings.merge(:ARGV => ['start'])
|
102
|
+
Daemons.run_proc('with_lock', options) do
|
103
|
+
DRb.start_service(WithLock::Server::url,WithLock::Server)
|
104
|
+
DRb.thread.join
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.run_service
|
109
|
+
return if started?
|
110
|
+
DRb.start_service(WithLock::Server::url,WithLock::Server)
|
111
|
+
DRb.thread.join
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.stop_service
|
115
|
+
return unless started?
|
116
|
+
`kill #{pid}`
|
117
|
+
FileUtils.rm_f(pidfile)
|
118
|
+
end
|
119
|
+
end
|
data/script/with_lock
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- encoding: utf-8 -*-
|
3
|
+
$:.push File.expand_path(File.join('..','..','lib'), __FILE__)
|
4
|
+
|
5
|
+
require "rubygems"
|
6
|
+
require "bundler"
|
7
|
+
Bundler.setup
|
8
|
+
|
9
|
+
FileUtils.mkdir_p('tmp/pids') unless File.exists?('tmp/pids')
|
10
|
+
|
11
|
+
require 'with_lock'
|
12
|
+
if ARGV.include?('start')
|
13
|
+
begin
|
14
|
+
locker = WithLock::Client.locker
|
15
|
+
rescue WithLock::LockException => e
|
16
|
+
puts "Starting WithLock on #{WithLock::Server::url}!"
|
17
|
+
WithLock::Server::start_service
|
18
|
+
locker = WithLock::Client.locker
|
19
|
+
end
|
20
|
+
puts "Clearing WithLock locks!"
|
21
|
+
locker = WithLock::Client.locker
|
22
|
+
locker.locks.each_pair do |lock,data|
|
23
|
+
pid = data[:owner].split('|').last
|
24
|
+
if locker.running?(pid) || !data[:owner].include?(`hostname`.strip)
|
25
|
+
puts "Running - pid"
|
26
|
+
else
|
27
|
+
puts "Not Running - pid"
|
28
|
+
locker.release(data[:owner],lock)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
elsif ARGV.include?('stop')
|
32
|
+
puts "Stopping WithLock!"
|
33
|
+
WithLock::Server::stop_service
|
34
|
+
elsif ARGV.include?('run')
|
35
|
+
puts "Running WithLock!"
|
36
|
+
WithLock::Server::run_service
|
37
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- encoding: utf-8 -*-
|
3
|
+
|
4
|
+
$:.push File.expand_path(File.join('..','..','lib'), __FILE__)
|
5
|
+
|
6
|
+
require "rubygems"
|
7
|
+
require "bundler"
|
8
|
+
Bundler.setup
|
9
|
+
|
10
|
+
require 'with_lock'
|
11
|
+
include WithLock::Public
|
12
|
+
|
13
|
+
begin
|
14
|
+
with_lock(ARGV[0],ARGV[1].to_f||0.5) do
|
15
|
+
sleep ARGV[2].to_f
|
16
|
+
Kernel.exit! if ARGV[3].eql?('kernel_exit')
|
17
|
+
exit(0) if ARGV[2].eql?('exit')
|
18
|
+
end
|
19
|
+
rescue WithLock::LockException => e
|
20
|
+
puts exit(1)
|
21
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.join('..','spec','spec_helper'), File.dirname(__FILE__))
|
3
|
+
|
4
|
+
describe WithLock do
|
5
|
+
describe "#settings" do
|
6
|
+
it "should have default settings" do
|
7
|
+
WithLock::Client::settings.should == {
|
8
|
+
'url' => 'druby://localhost:9999',
|
9
|
+
'directory' => 'tmp',
|
10
|
+
'scope' => 'with_lock'
|
11
|
+
}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#url" do
|
16
|
+
it "returns the druby url from settings" do
|
17
|
+
WithLock::Client::settings['url'].should == WithLock::Client::url
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#running(pid)" do
|
22
|
+
it "should report if given process id represents a running pid" do
|
23
|
+
WithLock::Server::running?($$).should be_true
|
24
|
+
end
|
25
|
+
it "should report if given process id doesn't represent a running pid" do
|
26
|
+
pid = `spec/support/echo_pid.sh`.to_s.strip
|
27
|
+
sleep 0.2
|
28
|
+
WithLock::Server::running?(pid).should be_false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#with_lock" do
|
33
|
+
it "should raise an exception if with_lock server not started" do
|
34
|
+
WithLock::Server.stop_service
|
35
|
+
started_trying = Time.now
|
36
|
+
while WithLock::Server.started? do
|
37
|
+
sleep 0.2
|
38
|
+
raise Exception.new("Couldn't stop server!") unless (Time.now - 3.seconds) > started_trying
|
39
|
+
end
|
40
|
+
error_message = ''
|
41
|
+
begin
|
42
|
+
with_lock('my_lock') do
|
43
|
+
"I should not get here!".should be_nil
|
44
|
+
end
|
45
|
+
rescue WithLock::LockException => e
|
46
|
+
e.message.should == "Couldn't connect to locker."
|
47
|
+
end
|
48
|
+
end
|
49
|
+
describe "when the server is running" do
|
50
|
+
before(:all) do
|
51
|
+
`script/with_lock start`
|
52
|
+
started_trying = Time.now
|
53
|
+
while !WithLock::Server.started? do
|
54
|
+
sleep 0.2
|
55
|
+
raise Exception.new("Couldn't start server!") unless (Time.now - 3.seconds) > started_trying
|
56
|
+
end
|
57
|
+
@locker = WithLock::Client.locker
|
58
|
+
end
|
59
|
+
after(:all) do
|
60
|
+
`script/with_lock stop`
|
61
|
+
while WithLock::Server.started? do
|
62
|
+
sleep 0.1
|
63
|
+
end
|
64
|
+
end
|
65
|
+
it "should grab the named lock if its not locked" do
|
66
|
+
with_lock('name') do
|
67
|
+
WithLock::Client.mine?('name').should be_true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
it "should not allow another process to grab the same named lock" do
|
71
|
+
system("spec/support/get_lock.rb name 0.5 10 &")
|
72
|
+
sleep 1
|
73
|
+
expect {
|
74
|
+
with_lock('name',0.5) do
|
75
|
+
end
|
76
|
+
}.to raise_exception(WithLock::LockException)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should have a counter of 1 when it first grabs the lock" do
|
80
|
+
with_lock('blarg') do
|
81
|
+
@locker.count(WithLock::Client.scoped_name('blarg')).should == 1
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should allow the same process to grab the same lock and increment its counter" do
|
86
|
+
with_lock('blarg') do
|
87
|
+
with_lock('blarg') do
|
88
|
+
@locker.count(WithLock::Client.scoped_name('blarg')).should == 2
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should decrement a lock's counter when it ends the block" do
|
94
|
+
with_lock('blarg') do
|
95
|
+
with_lock('blarg') do
|
96
|
+
end
|
97
|
+
@locker.count(WithLock::Client.scoped_name('blarg')).should == 1
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should release the lock when the block ends" do
|
102
|
+
with_lock('blarg') do
|
103
|
+
end
|
104
|
+
@locker.locks[WithLock::Client.scoped_name('blarg')].should be_nil
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should release the lock if an exception closes the block" do
|
108
|
+
begin
|
109
|
+
with_lock('blarg') do
|
110
|
+
raise "Blarg!!"
|
111
|
+
end
|
112
|
+
rescue => e
|
113
|
+
end
|
114
|
+
@locker.locks[WithLock::Client.scoped_name('blarg')].should be_nil
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should release the lock on a clean exit" do
|
118
|
+
`spec/support/get_lock.rb blarg 0.3 exit`
|
119
|
+
sleep 0.2
|
120
|
+
@locker.locks[WithLock::Client.scoped_name('blarg')].should be_nil
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should release the lock on an immediate exit" do
|
124
|
+
`spec/support/get_lock.rb blarg 0.3 kernel_exit`
|
125
|
+
sleep 0.2
|
126
|
+
@locker.locks[WithLock::Client.scoped_name('blarg')].should be_nil
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
data/with_lock.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require 'with_lock/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "with_lock"
|
7
|
+
s.version = WithLock::VERSION
|
8
|
+
s.authors = ["Christopher Louis Hauboldt"]
|
9
|
+
s.email = ["chris@hauboldt.us"]
|
10
|
+
s.homepage = "https://github.com/chrisboy333/with_lock"
|
11
|
+
s.summary = %q{Implements named mutexes for ruby applications.}
|
12
|
+
s.description = %q{Implements named mutexes for ruby applications by creating a resource server to query for locks.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "with_lock"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "rspec"
|
22
|
+
s.add_dependency "daemons"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: with_lock
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4.alpha
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Christopher Louis Hauboldt
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: daemons
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Implements named mutexes for ruby applications by creating a resource
|
42
|
+
server to query for locks.
|
43
|
+
email:
|
44
|
+
- chris@hauboldt.us
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- .gitignore
|
50
|
+
- .rspec
|
51
|
+
- Gemfile
|
52
|
+
- Gemfile.lock
|
53
|
+
- README.md
|
54
|
+
- Rakefile
|
55
|
+
- config/with_lock.local.yml
|
56
|
+
- config/with_lock.yml
|
57
|
+
- lib/with_lock.rb
|
58
|
+
- lib/with_lock/client.rb
|
59
|
+
- lib/with_lock/server.rb
|
60
|
+
- lib/with_lock/version.rb
|
61
|
+
- script/with_lock
|
62
|
+
- spec/spec_helper.rb
|
63
|
+
- spec/support/echo_pid.sh
|
64
|
+
- spec/support/get_lock.rb
|
65
|
+
- spec/with_lock_spec.rb
|
66
|
+
- with_lock.gemspec
|
67
|
+
homepage: https://github.com/chrisboy333/with_lock
|
68
|
+
licenses: []
|
69
|
+
metadata: {}
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ! '>'
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 1.3.1
|
84
|
+
requirements: []
|
85
|
+
rubyforge_project: with_lock
|
86
|
+
rubygems_version: 2.2.2
|
87
|
+
signing_key:
|
88
|
+
specification_version: 4
|
89
|
+
summary: Implements named mutexes for ruby applications.
|
90
|
+
test_files:
|
91
|
+
- spec/spec_helper.rb
|
92
|
+
- spec/support/echo_pid.sh
|
93
|
+
- spec/support/get_lock.rb
|
94
|
+
- spec/with_lock_spec.rb
|