ruby_redis_lock 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []