lockable 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,5 @@
1
+ --require spec_helper
2
+ --order random
3
+ --colour
4
+ --format nested
5
+ --drb
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'pry'
6
+ gem 'rspec'
7
+ gem 'redis'
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # Lockable
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :default do
4
+ system "rake -T"
5
+ end
6
+
7
+ desc 'cleanup working copy'
8
+ task :clean do
9
+ FileUtils.rm_rf %w(coverage pkg) + Dir['log/*.log'] + Dir['tmp/*']
10
+ end
@@ -0,0 +1,3 @@
1
+ module Lockable
2
+ VERSION = '0.0.1'
3
+ end
data/lib/lockable.rb ADDED
@@ -0,0 +1,64 @@
1
+ require 'lockable/version'
2
+
3
+ module Lockable
4
+
5
+ class << self
6
+
7
+ attr_accessor :redis
8
+ attr_writer :lock_timeout
9
+
10
+ DEFAULT_LOCK_TIMEOUT = 5 * 60 * 60
11
+
12
+ def lock_timeout
13
+ @lock_timeout || DEFAULT_LOCK_TIMEOUT
14
+ end
15
+
16
+ end
17
+
18
+ def lock!(holder)
19
+ raise ArgumentError unless holder
20
+
21
+ return true if acquire_lock(holder)
22
+
23
+ if locked? and lock_holder == holder.to_s
24
+ return extend_lock
25
+ end
26
+
27
+ false
28
+ end
29
+
30
+ def locked?
31
+ !!lock_holder
32
+ end
33
+
34
+ def unlock!
35
+ !!redis.del(lock_key)
36
+ end
37
+
38
+ def lock_holder
39
+ redis.get(lock_key)
40
+ end
41
+
42
+ def lock_timeout
43
+ redis.ttl(lock_key).to_i
44
+ end
45
+
46
+ private
47
+
48
+ def acquire_lock(holder)
49
+ !!redis.set(lock_key, holder, ex: Lockable.lock_timeout, nx: true)
50
+ end
51
+
52
+ def extend_lock
53
+ !!redis.expire(lock_key, Lockable.lock_timeout)
54
+ end
55
+
56
+ def lock_key
57
+ "lock:#{self.class.name.downcase}:#{id}"
58
+ end
59
+
60
+ def redis
61
+ Lockable.redis
62
+ end
63
+
64
+ end
data/lockable.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+
4
+ $LOAD_PATH.unshift lib
5
+
6
+ require 'lockable/version'
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = 'lockable'
10
+ spec.version = Lockable::VERSION
11
+ spec.authors = ['cmertz']
12
+ spec.email = ['chris@nimel.de']
13
+ spec.description = 'minimalist locking using redis'
14
+ spec.summary = 'minimalist locking using redis'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'rake'
23
+
24
+ spec.add_dependency 'redis'
25
+ end
@@ -0,0 +1,114 @@
1
+ require 'ostruct'
2
+
3
+ describe Lockable do
4
+
5
+ subject do
6
+ OpenStruct.new(id: 1).extend(Lockable)
7
+ end
8
+
9
+ before do
10
+ Lockable.redis.del(subject.send(:lock_key))
11
+ end
12
+
13
+ describe '#lock!' do
14
+
15
+ it 'needs a lock holder' do
16
+ expect { subject.lock!(nil) }.to raise_error(ArgumentError)
17
+ end
18
+
19
+ it 'locks' do
20
+ subject.lock!('toto').should be_true
21
+ end
22
+
23
+ context 'already locked' do
24
+
25
+ before do
26
+ Lockable.lock_timeout = 10
27
+ subject.lock!('toto')
28
+ end
29
+
30
+ it 'does not lock again' do
31
+ subject.lock!('tata')
32
+ subject.lock_holder.should eq 'toto'
33
+ end
34
+
35
+ it 'extends the ttl' do
36
+ Lockable.lock_timeout = 100
37
+ subject.lock!('toto')
38
+ subject.lock_timeout.should eq 100
39
+ end
40
+
41
+ it 'does not extend the ttl' do
42
+ Lockable.lock_timeout = 100
43
+ subject.lock!('tata')
44
+ subject.lock_timeout.should eq 10
45
+ end
46
+
47
+ end
48
+ end
49
+
50
+ describe '#lock_timeout' do
51
+
52
+ it 'does not have a timeout if not locked' do
53
+ subject.lock_timeout.should == -1
54
+ end
55
+
56
+ it 'sets a ttl' do
57
+ subject.lock!('toto')
58
+ subject.lock_timeout.should_not be_nil
59
+ end
60
+
61
+ end
62
+
63
+ describe '#locked?' do
64
+
65
+ it { should_not be_locked }
66
+
67
+ it 'should be locked' do
68
+ expect { subject.lock!('toto') }.to change{
69
+ subject.locked?
70
+ }.from(false).to(true)
71
+ end
72
+
73
+ end
74
+
75
+ describe '#unlock!' do
76
+
77
+ before do
78
+ subject.lock!('toto')
79
+ end
80
+
81
+ it 'is not locked anymore' do
82
+ expect { subject.unlock! }.to change{
83
+ subject.locked?
84
+ }.from(true).to(false)
85
+ end
86
+
87
+ it 'does not have a lock_holder anymore' do
88
+ expect { subject.unlock! }.to change{
89
+ subject.lock_holder
90
+ }.from('toto').to(nil)
91
+ end
92
+
93
+ it 'does not have a lock_timeout anymore' do
94
+ expect { subject.unlock! }.to change{
95
+ subject.lock_timeout
96
+ }.to(-1)
97
+ end
98
+
99
+ end
100
+
101
+ describe '#lock_holder' do
102
+
103
+ it 'does not have one' do
104
+ subject.lock_holder.should be nil
105
+ end
106
+
107
+ it 'does have one' do
108
+ subject.lock!('toto')
109
+ subject.lock_holder.should eq 'toto'
110
+ end
111
+
112
+ end
113
+
114
+ end
@@ -0,0 +1,5 @@
1
+ Bundler.require
2
+
3
+ require 'lockable'
4
+
5
+ Lockable.redis = Redis.new
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lockable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - cmertz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-11-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.3'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: redis
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: minimalist locking using redis
63
+ email:
64
+ - chris@nimel.de
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - .rspec
71
+ - Gemfile
72
+ - README.md
73
+ - Rakefile
74
+ - lib/lockable.rb
75
+ - lib/lockable/version.rb
76
+ - lockable.gemspec
77
+ - spec/lockable_spec.rb
78
+ - spec/spec_helper.rb
79
+ homepage:
80
+ licenses: []
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ segments:
92
+ - 0
93
+ hash: 3763012555333573935
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ segments:
101
+ - 0
102
+ hash: 3763012555333573935
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 1.8.25
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: minimalist locking using redis
109
+ test_files:
110
+ - spec/lockable_spec.rb
111
+ - spec/spec_helper.rb