redis-semaphore 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -0,0 +1,89 @@
1
+ redis-semaphore
2
+ ===============
3
+
4
+ Implements a mutex and semaphore using Redis and the neat BLPOP command.
5
+
6
+ The mutex and semaphore is blocking, not polling, and has a fair queue serving processes on a first-come, first-serve basis.
7
+
8
+ For more info see [Wikipedia](http://en.wikipedia.org/wiki/Semaphore_(programming\)).
9
+
10
+ Usage
11
+ -----
12
+
13
+ First let's see how to create a mutex:
14
+
15
+ ```ruby
16
+ s = Redis::Semaphore.new(:semaphore_name, :connection => "localhost")
17
+ s.lock do
18
+ # We're now in a mutex protected area
19
+ # No matter how many processes are running this program,
20
+ # there will be only one running this code block at a time.
21
+ do_something_speshiul()
22
+ end
23
+ ```
24
+
25
+ While our application is inside the code block given to ```s.lock```, other calls to use the mutex with the same name will block until our code block is finished. Once our mutex unlocks, the next process will unblock and be able to execute the code block. The blocking processes get unblocked in order of arrival, creating a fair queue.
26
+
27
+ You can also allow a set number of processes inside the semaphore-protected block:
28
+
29
+ ```ruby
30
+ s = Redis::Semaphore.new(:semaphore_name, 5, :connection => "localhost")
31
+ s.lock do
32
+ # Up to five processes at a time will be able to get inside this code
33
+ # block simultaneously.
34
+ do_something_less_speshiul()
35
+ end
36
+ ```
37
+
38
+ You don't need to use code blocks, you can also use linear code:
39
+
40
+ ```ruby
41
+ s = Redis::Semaphore.new(:semaphore_name, :connection => "localhost")
42
+ s.lock
43
+ do_something_speshiul()
44
+ s.unlock # Don't forget this, or the mutex will be locked forever!
45
+ ```
46
+
47
+ If you don't want to wait forever until the mutex or semaphore release, you can use a timeout, in seconds:
48
+
49
+ ```ruby
50
+ if s.lock(5) # This will only block for at most 5 seconds if the mutex stays locked.
51
+ do_something_speshiul()
52
+ s.unlock
53
+ else
54
+ puts "Aborted."
55
+ end
56
+ ```
57
+
58
+ You can check if the mutex or semaphore already exists, or how many resources are left in the semaphore:
59
+
60
+ ```ruby
61
+ puts "Someone already initialized this mutex or semaphore!" if s.exists?
62
+ puts "There are #{s.available} resources available right now."
63
+ ```
64
+
65
+ In the constructor you can pass in any arguments that you would pass to a regular Redis constructor. You can even pass in your custom Redis client:
66
+
67
+ ```ruby
68
+ r = Redis.new(:connection => "localhost", :db => 222)
69
+ s = Redis::Semaphore.new(:another_name, r)
70
+ #...
71
+ ```
72
+
73
+
74
+
75
+ Installation
76
+ ------------
77
+
78
+ $ gem install redis-semaphore
79
+
80
+ Testing
81
+ -------
82
+
83
+ $ bundle install
84
+ $ rake
85
+
86
+ Author
87
+ ------
88
+
89
+ [David Verhasselt](http://davidverhasselt.com) - david@crowdway.com
@@ -40,8 +40,11 @@ class Redis
40
40
 
41
41
  @locked = true
42
42
  if block_given?
43
- yield
44
- unlock
43
+ begin
44
+ yield
45
+ ensure
46
+ unlock
47
+ end
45
48
  end
46
49
 
47
50
  true
data/spec/redis_spec.rb CHANGED
@@ -49,5 +49,22 @@ describe "redis" do
49
49
  end
50
50
  code_executed.should == true
51
51
  end
52
-
53
- end
52
+
53
+ it "should pass an exception right through" do
54
+ lambda do
55
+ @semaphore.lock do
56
+ raise Exception, "redis semaphore exception"
57
+ end
58
+ end.should raise_error(Exception, "redis semaphore exception")
59
+ end
60
+
61
+ it "should not leave the semaphore locked after raising an exception" do
62
+ lambda do
63
+ @semaphore.lock do
64
+ raise Exception
65
+ end
66
+ end.should raise_error
67
+
68
+ @semaphore.locked?.should == false
69
+ end
70
+ end
data/spec/spec_helper.rb CHANGED
@@ -10,9 +10,3 @@ require 'logger'
10
10
  $TESTING=true
11
11
  $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
12
12
  require 'redis/semaphore'
13
-
14
- RSpec::Matchers.define :have_key do |expected|
15
- match do |redis|
16
- redis.exists(expected)
17
- end
18
- end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 0
9
- version: 0.1.0
8
+ - 1
9
+ version: 0.1.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - David Verhasselt
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-08-05 00:00:00 +02:00
17
+ date: 2011-09-18 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency