ruby_redis_lock 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/.loadpath +5 -0
  2. data/.project +17 -0
  3. data/Gemfile +5 -0
  4. data/Gemfile.lock +31 -0
  5. data/Readme.md +85 -0
  6. data/coverage/.resultset.json +240 -0
  7. data/coverage/assets/0.5.3/app.js +88 -0
  8. data/coverage/assets/0.5.3/fancybox/blank.gif +0 -0
  9. data/coverage/assets/0.5.3/fancybox/fancy_close.png +0 -0
  10. data/coverage/assets/0.5.3/fancybox/fancy_loading.png +0 -0
  11. data/coverage/assets/0.5.3/fancybox/fancy_nav_left.png +0 -0
  12. data/coverage/assets/0.5.3/fancybox/fancy_nav_right.png +0 -0
  13. data/coverage/assets/0.5.3/fancybox/fancy_shadow_e.png +0 -0
  14. data/coverage/assets/0.5.3/fancybox/fancy_shadow_n.png +0 -0
  15. data/coverage/assets/0.5.3/fancybox/fancy_shadow_ne.png +0 -0
  16. data/coverage/assets/0.5.3/fancybox/fancy_shadow_nw.png +0 -0
  17. data/coverage/assets/0.5.3/fancybox/fancy_shadow_s.png +0 -0
  18. data/coverage/assets/0.5.3/fancybox/fancy_shadow_se.png +0 -0
  19. data/coverage/assets/0.5.3/fancybox/fancy_shadow_sw.png +0 -0
  20. data/coverage/assets/0.5.3/fancybox/fancy_shadow_w.png +0 -0
  21. data/coverage/assets/0.5.3/fancybox/fancy_title_left.png +0 -0
  22. data/coverage/assets/0.5.3/fancybox/fancy_title_main.png +0 -0
  23. data/coverage/assets/0.5.3/fancybox/fancy_title_over.png +0 -0
  24. data/coverage/assets/0.5.3/fancybox/fancy_title_right.png +0 -0
  25. data/coverage/assets/0.5.3/fancybox/fancybox-x.png +0 -0
  26. data/coverage/assets/0.5.3/fancybox/fancybox-y.png +0 -0
  27. data/coverage/assets/0.5.3/fancybox/fancybox.png +0 -0
  28. data/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.css +363 -0
  29. data/coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.pack.js +44 -0
  30. data/coverage/assets/0.5.3/favicon_green.png +0 -0
  31. data/coverage/assets/0.5.3/favicon_red.png +0 -0
  32. data/coverage/assets/0.5.3/favicon_yellow.png +0 -0
  33. data/coverage/assets/0.5.3/highlight.css +129 -0
  34. data/coverage/assets/0.5.3/highlight.pack.js +1 -0
  35. data/coverage/assets/0.5.3/jquery-1.6.2.min.js +18 -0
  36. data/coverage/assets/0.5.3/jquery.dataTables.min.js +152 -0
  37. data/coverage/assets/0.5.3/jquery.timeago.js +141 -0
  38. data/coverage/assets/0.5.3/jquery.url.js +174 -0
  39. data/coverage/assets/0.5.3/loading.gif +0 -0
  40. data/coverage/assets/0.5.3/magnify.png +0 -0
  41. data/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  42. data/coverage/assets/0.5.3/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  43. data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  44. data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  45. data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  46. data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  47. data/coverage/assets/0.5.3/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  48. data/coverage/assets/0.5.3/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  49. data/coverage/assets/0.5.3/smoothness/images/ui-icons_222222_256x240.png +0 -0
  50. data/coverage/assets/0.5.3/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  51. data/coverage/assets/0.5.3/smoothness/images/ui-icons_454545_256x240.png +0 -0
  52. data/coverage/assets/0.5.3/smoothness/images/ui-icons_888888_256x240.png +0 -0
  53. data/coverage/assets/0.5.3/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  54. data/coverage/assets/0.5.3/smoothness/jquery-ui-1.8.4.custom.css +295 -0
  55. data/coverage/assets/0.5.3/stylesheet.css +383 -0
  56. data/coverage/index.html +1575 -0
  57. data/lib/ruby_redis_lock.rb +9 -0
  58. data/lib/ruby_redis_lock/ruby_redis_lock.rb +66 -0
  59. data/redis_test.bat +2 -0
  60. data/ruby_redis_lock.gemspec +21 -0
  61. data/ruby_redis_lock.rdb +1 -0
  62. data/spec/acquire_lock_spec.rb +44 -0
  63. data/spec/lock_spec.rb +73 -0
  64. data/spec/release_lock_spec.rb +22 -0
  65. data/spec/spec_helper.rb +20 -0
  66. data/spec/try_acquire_lock_spec.rb +31 -0
  67. data/test.conf +1 -0
  68. metadata +112 -0
@@ -0,0 +1,9 @@
1
+ require 'redis'
2
+
3
+ require File.expand_path('../ruby_redis_lock/ruby_redis_lock', __FILE__)
4
+
5
+
6
+ class Redis
7
+ include RubyRedisLock
8
+
9
+ end
@@ -0,0 +1,66 @@
1
+ module RubyRedisLock
2
+
3
+
4
+ def lock(lock_name, processing_timeout=60, acquiring_timout=10)
5
+ acquire_lock(lock_name, processing_timeout, acquiring_timout)
6
+ yield
7
+ ensure
8
+ release_lock(lock_name, processing_timeout)
9
+ end
10
+
11
+
12
+ private
13
+ def acquire_lock(lock_name, processing_timeout=60, acquiring_timeout=10)
14
+
15
+ start_time = Time.now.to_i
16
+
17
+ while !try_acquire_lock(lock_name, processing_timeout)
18
+
19
+ sleep(rand(100).to_f/100.0)
20
+
21
+ if (Time.now.to_i - start_time) > acquiring_timeout
22
+ raise Exception, "Acquiring lock timeout > #{acquiring_timeout} seconds"
23
+ end
24
+
25
+ end
26
+
27
+ return true
28
+
29
+ end
30
+
31
+ def try_acquire_lock(lock_name, processing_timeout=60)
32
+
33
+ ret = self.setnx(ruby_redis_lock_key(lock_name), "#{Time.now.to_i + processing_timeout}")
34
+ return true if ret == true
35
+
36
+ expiration = self.get(ruby_redis_lock_key(lock_name)).to_i
37
+ return false if Time.now.to_i < expiration
38
+
39
+ previous_expiration = self.getset(ruby_redis_lock_key(lock_name), "#{Time.now.to_i + processing_timeout}").to_i
40
+ return true if expiration == previous_expiration
41
+
42
+ return false
43
+
44
+ end
45
+
46
+ def release_lock(lock_name, processing_timeout=60)
47
+
48
+ expiration = self.get(ruby_redis_lock_key(lock_name)).to_i
49
+ return false if Time.now.to_i > expiration
50
+
51
+ previous_expiration = self.getset(ruby_redis_lock_key(lock_name), "#{Time.now.to_i + processing_timeout}").to_i
52
+
53
+ if expiration == previous_expiration # it still owns the lock
54
+ self.del(ruby_redis_lock_key(lock_name))
55
+ return true
56
+ end
57
+
58
+ return false
59
+ end
60
+
61
+ def ruby_redis_lock_key(lock_name)
62
+ "RubyRedisLock:#{lock_name}"
63
+ end
64
+
65
+
66
+ end
data/redis_test.bat ADDED
@@ -0,0 +1,2 @@
1
+ "C:\redis\redis-server" test.conf
2
+ pause
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "ruby_redis_lock"
6
+ s.version = "0.1.0"
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Tanin Na Nakorn"]
9
+ s.email = ["tanin47@yahoo.com"]
10
+ s.homepage = "http://github.com/tanin47/ruby_redis_lock"
11
+ s.summary = %q{RubyRedisLock is a distributed lock for Ruby (using Redis)}
12
+ s.description = %q{distributed lock for Ruby (using Redis)}
13
+
14
+ s.rubyforge_project = "ruby_redis_lock"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {coverage,spec}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ end
@@ -0,0 +1 @@
1
+ REDIS0001�
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'acquire_lock' do
4
+
5
+ it "acquires the lock if it does not exist" do
6
+ @redis.send(:acquire_lock, "test").should == true
7
+ end
8
+
9
+ it "acquires the lock if it is expired" do
10
+
11
+ @redis.send(:acquire_lock, "test", 0.1).should == true
12
+
13
+ sleep(1)
14
+ @redis.send(:acquire_lock, "test").should == true
15
+
16
+ end
17
+
18
+ it "raise errors when acquiring the lock takes too long" do
19
+
20
+ @redis.send(:acquire_lock, "test", 60, 60).should == true
21
+
22
+ lambda { @redis.send(:acquire_lock, "test", 60, 1) }.should raise_error
23
+
24
+ end
25
+
26
+ it "waits until the other thread finishes and acquire lock" do
27
+
28
+ start_time = Time.now.to_i
29
+ @redis.send(:acquire_lock, "test", 60, 60).should == true
30
+
31
+ Thread.new {
32
+ Thread.current.join(1)
33
+ sleep(5)
34
+ @redis.send(:release_lock, "test", 60).should == true
35
+ }
36
+
37
+ Thread.current.join(1)
38
+ @redis.send(:acquire_lock, "test", 60, 20).should == true
39
+
40
+ (Time.now.to_i - start_time).should be > 4
41
+
42
+ end
43
+
44
+ end
data/spec/lock_spec.rb ADDED
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'lock' do
4
+
5
+ it "acquires the lock if it does not exist" do
6
+
7
+ @redis.lock("test") { }
8
+
9
+ end
10
+
11
+ it "waits and acquire lock" do
12
+
13
+ start_time = Time.now.to_i
14
+
15
+ Thread.new {
16
+ @redis.lock("test") {
17
+ Thread.current.join(1)
18
+ sleep(5)
19
+ }
20
+ }
21
+
22
+ Thread.current.join(1)
23
+
24
+ @redis.lock("test") { }
25
+
26
+ (Time.now.to_i - start_time).should be > 4
27
+
28
+ end
29
+
30
+ it "waits and acquire expired lock" do
31
+
32
+ start_time = Time.now.to_i
33
+
34
+ Thread.new {
35
+ @redis.send(:acquire_lock, "test", 5, 10).should == true
36
+ }
37
+
38
+ Thread.current.join(0.1)
39
+
40
+ @redis.lock("test") { }
41
+
42
+ (Time.now.to_i - start_time).should be > 4
43
+
44
+ end
45
+
46
+ it "fails to acquire lock" do
47
+
48
+ Thread.new {
49
+ @redis.lock("test") {
50
+ Thread.current.join(1)
51
+ sleep(5)
52
+ }
53
+ }
54
+
55
+ Thread.current.join(1)
56
+ lambda { @redis.lock("test", 10, 2) { } }.should raise_error
57
+
58
+ end
59
+
60
+ it "correctly release the lock when error is raised" do
61
+
62
+ begin
63
+ @redis.lock("test") {
64
+ raise 'some error'
65
+ }
66
+ rescue
67
+ end
68
+
69
+ @redis.get(@redis.send(:ruby_redis_lock_key, "test")).should == nil
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'release_lock' do
4
+
5
+ it "release lock when the lock is not expired" do
6
+
7
+ @redis.send(:acquire_lock, "test", 69).should == true
8
+
9
+ @redis.send(:release_lock, "test").should == true
10
+
11
+ end
12
+
13
+ it "does not release lock if the lock is already expired" do
14
+
15
+ @redis.send(:acquire_lock, "test", 0.1).should == true
16
+
17
+ sleep(1)
18
+ @redis.send(:release_lock, "test").should == false
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ coverage_dir("coverage")
5
+ end
6
+
7
+ require 'rspec'
8
+
9
+ require File.expand_path("../../lib/ruby_redis_lock",__FILE__)
10
+
11
+ RSpec.configure do |config|
12
+
13
+ config.mock_with :rspec
14
+
15
+ config.before(:each) do
16
+ @redis = Redis.new
17
+ @redis.flushall
18
+ end
19
+
20
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'try_acquire_lock' do
4
+
5
+ it "acquires lock when the lock does not exist" do
6
+
7
+ @redis.send(:try_acquire_lock, "test").should == true
8
+
9
+ end
10
+
11
+ it "does not acquire lock when the lock is alive" do
12
+
13
+ @redis.send(:try_acquire_lock, "test").should == true
14
+ @redis.send(:try_acquire_lock, "test").should == false
15
+
16
+ end
17
+
18
+ it "acquires lock when the lock is expired" do
19
+
20
+ @redis.send(:try_acquire_lock, "test", 0.1).should == true
21
+
22
+ sleep(1)
23
+ @redis.send(:try_acquire_lock, "test").should == true
24
+
25
+ end
26
+
27
+ it "does not acquire lock when the lock is expired but somebody else already successfully acquire the same lock" do
28
+
29
+ end
30
+
31
+ end
data/test.conf ADDED
@@ -0,0 +1 @@
1
+ dbfilename ruby_redis_lock.rdb
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_redis_lock
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tanin Na Nakorn
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-09-29 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: distributed lock for Ruby (using Redis)
15
+ email:
16
+ - tanin47@yahoo.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .loadpath
22
+ - .project
23
+ - Gemfile
24
+ - Gemfile.lock
25
+ - Readme.md
26
+ - coverage/.resultset.json
27
+ - coverage/assets/0.5.3/app.js
28
+ - coverage/assets/0.5.3/fancybox/blank.gif
29
+ - coverage/assets/0.5.3/fancybox/fancy_close.png
30
+ - coverage/assets/0.5.3/fancybox/fancy_loading.png
31
+ - coverage/assets/0.5.3/fancybox/fancy_nav_left.png
32
+ - coverage/assets/0.5.3/fancybox/fancy_nav_right.png
33
+ - coverage/assets/0.5.3/fancybox/fancy_shadow_e.png
34
+ - coverage/assets/0.5.3/fancybox/fancy_shadow_n.png
35
+ - coverage/assets/0.5.3/fancybox/fancy_shadow_ne.png
36
+ - coverage/assets/0.5.3/fancybox/fancy_shadow_nw.png
37
+ - coverage/assets/0.5.3/fancybox/fancy_shadow_s.png
38
+ - coverage/assets/0.5.3/fancybox/fancy_shadow_se.png
39
+ - coverage/assets/0.5.3/fancybox/fancy_shadow_sw.png
40
+ - coverage/assets/0.5.3/fancybox/fancy_shadow_w.png
41
+ - coverage/assets/0.5.3/fancybox/fancy_title_left.png
42
+ - coverage/assets/0.5.3/fancybox/fancy_title_main.png
43
+ - coverage/assets/0.5.3/fancybox/fancy_title_over.png
44
+ - coverage/assets/0.5.3/fancybox/fancy_title_right.png
45
+ - coverage/assets/0.5.3/fancybox/fancybox-x.png
46
+ - coverage/assets/0.5.3/fancybox/fancybox-y.png
47
+ - coverage/assets/0.5.3/fancybox/fancybox.png
48
+ - coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.css
49
+ - coverage/assets/0.5.3/fancybox/jquery.fancybox-1.3.1.pack.js
50
+ - coverage/assets/0.5.3/favicon_green.png
51
+ - coverage/assets/0.5.3/favicon_red.png
52
+ - coverage/assets/0.5.3/favicon_yellow.png
53
+ - coverage/assets/0.5.3/highlight.css
54
+ - coverage/assets/0.5.3/highlight.pack.js
55
+ - coverage/assets/0.5.3/jquery-1.6.2.min.js
56
+ - coverage/assets/0.5.3/jquery.dataTables.min.js
57
+ - coverage/assets/0.5.3/jquery.timeago.js
58
+ - coverage/assets/0.5.3/jquery.url.js
59
+ - coverage/assets/0.5.3/loading.gif
60
+ - coverage/assets/0.5.3/magnify.png
61
+ - coverage/assets/0.5.3/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
62
+ - coverage/assets/0.5.3/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
63
+ - coverage/assets/0.5.3/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
64
+ - coverage/assets/0.5.3/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
65
+ - coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_dadada_1x400.png
66
+ - coverage/assets/0.5.3/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
67
+ - coverage/assets/0.5.3/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
68
+ - coverage/assets/0.5.3/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
69
+ - coverage/assets/0.5.3/smoothness/images/ui-icons_222222_256x240.png
70
+ - coverage/assets/0.5.3/smoothness/images/ui-icons_2e83ff_256x240.png
71
+ - coverage/assets/0.5.3/smoothness/images/ui-icons_454545_256x240.png
72
+ - coverage/assets/0.5.3/smoothness/images/ui-icons_888888_256x240.png
73
+ - coverage/assets/0.5.3/smoothness/images/ui-icons_cd0a0a_256x240.png
74
+ - coverage/assets/0.5.3/smoothness/jquery-ui-1.8.4.custom.css
75
+ - coverage/assets/0.5.3/stylesheet.css
76
+ - coverage/index.html
77
+ - lib/ruby_redis_lock.rb
78
+ - lib/ruby_redis_lock/ruby_redis_lock.rb
79
+ - redis_test.bat
80
+ - ruby_redis_lock.gemspec
81
+ - ruby_redis_lock.rdb
82
+ - spec/acquire_lock_spec.rb
83
+ - spec/lock_spec.rb
84
+ - spec/release_lock_spec.rb
85
+ - spec/spec_helper.rb
86
+ - spec/try_acquire_lock_spec.rb
87
+ - test.conf
88
+ homepage: http://github.com/tanin47/ruby_redis_lock
89
+ licenses: []
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project: ruby_redis_lock
108
+ rubygems_version: 1.8.9
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: RubyRedisLock is a distributed lock for Ruby (using Redis)
112
+ test_files: []