redis-semaphore 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2011 by David Verhasselt (david@crowdway.com)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ task :default => :spec
2
+ task :test => :spec
3
+
4
+ desc "Run specs"
5
+ task :spec do
6
+ exec "rspec spec/redis_spec.rb"
7
+ end
@@ -0,0 +1 @@
1
+ require 'redis/semaphore'
@@ -0,0 +1,82 @@
1
+ require 'redis'
2
+
3
+ class Redis
4
+ class Semaphore
5
+
6
+ attr_reader :resources
7
+
8
+ # RedisSempahore.new(:my_semaphore, 5, myRedis)
9
+ # RedisSemaphore.new(:my_semaphore, myRedis)
10
+ # RedisSemaphore.new(:my_semaphore, :connection => "", :port => "")
11
+ # RedisSemaphore.new(:my_semaphore, :path => "bla")
12
+ def initialize(*args)
13
+ raise "Need at least two arguments" if args.size < 2
14
+
15
+ @locked = false
16
+ @name = args.shift.to_s
17
+ @redis = args.pop
18
+ @redis = Redis.new(@redis) unless @redis.kind_of? Redis
19
+ @resources = args.pop || 1
20
+
21
+ end
22
+
23
+ def available
24
+ @redis.llen(list_name)
25
+ end
26
+
27
+ def exists?
28
+ @redis.exists(exists_name)
29
+ end
30
+
31
+ def delete!
32
+ @redis.del(list_name)
33
+ @redis.del(exists_name)
34
+ end
35
+
36
+ def lock(timeout = 0)
37
+ exists_or_create!
38
+
39
+ return false if @redis.blpop(list_name, timeout).nil?
40
+
41
+ @locked = true
42
+ if block_given?
43
+ yield
44
+ unlock
45
+ end
46
+
47
+ true
48
+ end
49
+
50
+ def unlock
51
+ return false unless locked?
52
+
53
+ @redis.rpush(list_name, 1)
54
+ @locked = false
55
+ end
56
+
57
+ def locked?
58
+ @locked
59
+ end
60
+
61
+
62
+ private
63
+ def list_name
64
+ "SEMAPHORE::#{@name}::LIST"
65
+ end
66
+
67
+ def exists_name
68
+ "SEMAPHORE::#{@name}::EXISTS"
69
+ end
70
+
71
+ def exists_or_create!
72
+ exists = @redis.getset(exists_name, 1)
73
+
74
+ if "1" != exists
75
+ @resources.times do
76
+ @redis.lpush(list_name, 1)
77
+ end
78
+ end
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,53 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "redis" do
4
+ before(:all) do
5
+ # use database 15 for testing so we dont accidentally step on you real data
6
+ @redis = Redis.new :db => 15
7
+ @semaphore = Redis::Semaphore.new(:my_semaphore, @redis)
8
+ end
9
+
10
+ before(:each) do
11
+ @redis.flushdb
12
+ end
13
+
14
+ after(:each) do
15
+ @redis.flushdb
16
+ end
17
+
18
+ after(:all) do
19
+ @redis.quit
20
+ end
21
+
22
+ it "should be unlocked from the start" do
23
+ @semaphore.locked?.should == false
24
+ end
25
+
26
+ it "should lock and unlock" do
27
+ @semaphore.lock
28
+ @semaphore.locked?.should == true
29
+ @semaphore.unlock
30
+ @semaphore.locked?.should == false
31
+ end
32
+
33
+ it "should not lock twice as a mutex" do
34
+ @semaphore.lock
35
+ @semaphore.lock(1).should == false
36
+ end
37
+
38
+ it "should not lock three times when only two available" do
39
+ multisem = Redis::Semaphore.new(:my_semaphore2, 2, @redis)
40
+ multisem.lock.should == true
41
+ multisem.lock(1).should == true
42
+ multisem.lock(1).should == false
43
+ end
44
+
45
+ it "should execute the given code block" do
46
+ code_executed = false
47
+ @semaphore.lock do
48
+ code_executed = true
49
+ end
50
+ code_executed.should == true
51
+ end
52
+
53
+ end
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup(:default, :test)
4
+ Bundler.require(:default, :test)
5
+
6
+ require 'rspec'
7
+ require 'redis'
8
+ require 'logger'
9
+
10
+ $TESTING=true
11
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
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 ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redis-semaphore
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - David Verhasselt
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-08-05 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: redis
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ description: |
34
+ Implements a distributed semaphore or mutex using Redis.
35
+
36
+ email: david@crowdway.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - README.md
45
+ - Rakefile
46
+ - LICENSE
47
+ - lib/redis/semaphore.rb
48
+ - lib/redis-semaphore.rb
49
+ - spec/spec_helper.rb
50
+ - spec/redis_spec.rb
51
+ has_rdoc: true
52
+ homepage: http://github.com/dv/redis-semaphore
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.7
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: Implements a distributed semaphore or mutex using Redis.
83
+ test_files: []
84
+