mongoid-locker 0.1.1 → 0.2.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.
- data/.travis.yml +14 -0
- data/Appraisals +7 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +8 -6
- data/Gemfile.lock +80 -0
- data/README.md +2 -2
- data/Rakefile +2 -8
- data/VERSION +1 -1
- data/gemfiles/mongoid2.gemfile +24 -0
- data/gemfiles/mongoid3.gemfile +24 -0
- data/lib/mongoid/locker.rb +33 -20
- data/lib/mongoid/locker/wrapper.rb +42 -0
- data/mongoid-locker.gemspec +16 -5
- data/spec/database.yml +7 -0
- data/spec/mongoid-locker_spec.rb +51 -2
- data/spec/spec_helper.rb +1 -0
- metadata +48 -5
data/.travis.yml
CHANGED
@@ -7,3 +7,17 @@ rvm:
|
|
7
7
|
- jruby-19mode # JRuby in 1.9 mode
|
8
8
|
- rbx-18mode
|
9
9
|
- rbx-19mode
|
10
|
+
gemfile:
|
11
|
+
- gemfiles/mongoid2.gemfile
|
12
|
+
- gemfiles/mongoid3.gemfile
|
13
|
+
matrix:
|
14
|
+
exclude:
|
15
|
+
# not supported by Mongoid 3
|
16
|
+
- rvm: 1.8.7
|
17
|
+
gemfile: gemfiles/mongoid3.gemfile
|
18
|
+
- rvm: 1.9.2
|
19
|
+
gemfile: gemfiles/mongoid3.gemfile
|
20
|
+
- rvm: jruby-18mode
|
21
|
+
gemfile: gemfiles/mongoid3.gemfile
|
22
|
+
- rvm: rbx-18mode
|
23
|
+
gemfile: gemfiles/mongoid3.gemfile
|
data/Appraisals
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## HEAD ([diff](https://github.com/afeld/mongoid-locker/compare/v0.2.0...master?w=1))
|
4
|
+
|
5
|
+
## 0.2.0 ([diff](https://github.com/afeld/mongoid-locker/compare/v0.1.1...v0.2.0?w=1))
|
6
|
+
|
7
|
+
* handle recursive calls to `#with_lock` - #7
|
8
|
+
* lock optimizations, particularly for large documents
|
9
|
+
* add Mongoid 3 support - #3
|
10
|
+
|
3
11
|
## 0.1.1 ([diff](https://github.com/afeld/mongoid-locker/compare/v0.1.0...v0.1.1?w=1))
|
4
12
|
|
5
13
|
* fix for subclasses - #5
|
data/Gemfile
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
source 'http://rubygems.org'
|
2
|
-
# Add dependencies required to use your gem here.
|
3
|
-
# Example:
|
4
|
-
# gem 'activesupport', '>= 2.3.5'
|
5
2
|
|
6
|
-
gem 'mongoid', '
|
3
|
+
gem 'mongoid', '>= 2.4', '<= 3.1'
|
4
|
+
|
5
|
+
|
6
|
+
# groups need to be copied to gemfiles/*.gemfile
|
7
7
|
|
8
|
-
# Add dependencies to develop your gem here.
|
9
|
-
# Include everything needed to run rake, tests, features, etc.
|
10
8
|
group :development do
|
11
9
|
gem 'rspec', '~> 2.8'
|
12
10
|
gem 'bundler', '~> 1.1'
|
@@ -17,4 +15,8 @@ end
|
|
17
15
|
|
18
16
|
group :development, :test do
|
19
17
|
gem 'bson_ext', :platforms => :ruby
|
18
|
+
|
19
|
+
gem 'rake'
|
20
|
+
# v0.4.1 doesn't support multiple group names
|
21
|
+
gem 'appraisal', :git => 'git://github.com/thoughtbot/appraisal.git', :ref => 'ad2aeb99649f6a78f78be5009fb50306f06eaa9f'
|
20
22
|
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git://github.com/thoughtbot/appraisal.git
|
3
|
+
revision: ad2aeb99649f6a78f78be5009fb50306f06eaa9f
|
4
|
+
ref: ad2aeb99649f6a78f78be5009fb50306f06eaa9f
|
5
|
+
specs:
|
6
|
+
appraisal (0.4.1)
|
7
|
+
bundler
|
8
|
+
rake
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: http://rubygems.org/
|
12
|
+
specs:
|
13
|
+
activemodel (3.2.8)
|
14
|
+
activesupport (= 3.2.8)
|
15
|
+
builder (~> 3.0.0)
|
16
|
+
activesupport (3.2.8)
|
17
|
+
i18n (~> 0.6)
|
18
|
+
multi_json (~> 1.0)
|
19
|
+
bson (1.6.4)
|
20
|
+
bson_ext (1.6.4)
|
21
|
+
bson (~> 1.6.4)
|
22
|
+
builder (3.0.0)
|
23
|
+
diff-lcs (1.1.3)
|
24
|
+
ffi (1.1.5)
|
25
|
+
git (1.2.5)
|
26
|
+
guard (1.3.2)
|
27
|
+
listen (>= 0.4.2)
|
28
|
+
thor (>= 0.14.6)
|
29
|
+
guard-rspec (1.2.1)
|
30
|
+
guard (>= 1.1)
|
31
|
+
i18n (0.6.0)
|
32
|
+
jeweler (1.8.4)
|
33
|
+
bundler (~> 1.0)
|
34
|
+
git (>= 1.2.5)
|
35
|
+
rake
|
36
|
+
rdoc
|
37
|
+
json (1.7.5)
|
38
|
+
listen (0.4.7)
|
39
|
+
rb-fchange (~> 0.0.5)
|
40
|
+
rb-fsevent (~> 0.9.1)
|
41
|
+
rb-inotify (~> 0.8.8)
|
42
|
+
mongoid (3.0.5)
|
43
|
+
activemodel (~> 3.1)
|
44
|
+
moped (~> 1.1)
|
45
|
+
origin (~> 1.0)
|
46
|
+
tzinfo (~> 0.3.22)
|
47
|
+
moped (1.2.1)
|
48
|
+
multi_json (1.3.6)
|
49
|
+
origin (1.0.7)
|
50
|
+
rake (0.9.2.2)
|
51
|
+
rb-fchange (0.0.5)
|
52
|
+
ffi
|
53
|
+
rb-fsevent (0.9.1)
|
54
|
+
rb-inotify (0.8.8)
|
55
|
+
ffi (>= 0.5.0)
|
56
|
+
rdoc (3.12)
|
57
|
+
json (~> 1.4)
|
58
|
+
rspec (2.11.0)
|
59
|
+
rspec-core (~> 2.11.0)
|
60
|
+
rspec-expectations (~> 2.11.0)
|
61
|
+
rspec-mocks (~> 2.11.0)
|
62
|
+
rspec-core (2.11.1)
|
63
|
+
rspec-expectations (2.11.2)
|
64
|
+
diff-lcs (~> 1.1.3)
|
65
|
+
rspec-mocks (2.11.2)
|
66
|
+
thor (0.16.0)
|
67
|
+
tzinfo (0.3.33)
|
68
|
+
|
69
|
+
PLATFORMS
|
70
|
+
ruby
|
71
|
+
|
72
|
+
DEPENDENCIES
|
73
|
+
appraisal!
|
74
|
+
bson_ext
|
75
|
+
bundler (~> 1.1)
|
76
|
+
guard-rspec
|
77
|
+
jeweler (~> 1.8)
|
78
|
+
mongoid (>= 2.4, <= 3.1)
|
79
|
+
rake
|
80
|
+
rspec (~> 2.8)
|
data/README.md
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
|
3
3
|
Document-level locking for MongoDB via Mongoid. The need arose at [Jux](https://jux.com) from multiple processes on multiple servers trying to act upon the same document and stepping on each other's toes. Mongoid-Locker is an easy way to ensure only one process can perform a certain operation on a document at a time.
|
4
4
|
|
5
|
-
[Tested](http://travis-ci.org/afeld/mongoid-locker) against MRI 1.8.7, 1.9.2 and 1.9.3, Rubinius 1.8 and 1.9, and JRuby 1.8 and 1.9.
|
5
|
+
[Tested](http://travis-ci.org/afeld/mongoid-locker) against MRI 1.8.7, 1.9.2 and 1.9.3, Rubinius 1.8 and 1.9, and JRuby 1.8 and 1.9 with Mongoid 2 and 3 ([where supported](http://travis-ci.org/#!/afeld/mongoid-locker)).
|
6
6
|
|
7
7
|
## Usage
|
8
8
|
|
9
9
|
Add to your `Gemfile`:
|
10
10
|
|
11
11
|
```ruby
|
12
|
-
gem 'mongoid-locker', '~> 0.
|
12
|
+
gem 'mongoid-locker', '~> 0.2'
|
13
13
|
```
|
14
14
|
|
15
15
|
and run `bundle install`. In the model you wish to lock, include `Mongoid::Locker` after `Mongoid::Document`. For example:
|
data/Rakefile
CHANGED
@@ -1,15 +1,9 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
|
-
require 'bundler'
|
5
|
-
begin
|
6
|
-
Bundler.setup(:default, :development)
|
7
|
-
rescue Bundler::BundlerError => e
|
8
|
-
$stderr.puts e.message
|
9
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
-
exit e.status_code
|
11
|
-
end
|
4
|
+
require 'bundler/setup'
|
12
5
|
require 'rake'
|
6
|
+
require 'appraisal'
|
13
7
|
|
14
8
|
require 'jeweler'
|
15
9
|
Jeweler::Tasks.new do |gem|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# This file *was* generated by Appraisal
|
2
|
+
|
3
|
+
source 'http://rubygems.org'
|
4
|
+
|
5
|
+
gem 'mongoid', '~> 2.4'
|
6
|
+
|
7
|
+
|
8
|
+
###### added manually ######
|
9
|
+
|
10
|
+
group :development do
|
11
|
+
gem 'rspec', '~> 2.8'
|
12
|
+
gem 'bundler', '~> 1.1'
|
13
|
+
gem 'jeweler', '~> 1.8'
|
14
|
+
|
15
|
+
gem 'guard-rspec'
|
16
|
+
end
|
17
|
+
|
18
|
+
group :development, :test do
|
19
|
+
gem 'bson_ext', :platforms => :ruby
|
20
|
+
|
21
|
+
gem 'rake'
|
22
|
+
# v0.4.1 doesn't support multiple group names
|
23
|
+
gem 'appraisal', :git => 'git://github.com/thoughtbot/appraisal.git', :ref => 'ad2aeb99649f6a78f78be5009fb50306f06eaa9f'
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# This file *was* generated by Appraisal
|
2
|
+
|
3
|
+
source 'http://rubygems.org'
|
4
|
+
|
5
|
+
gem 'mongoid', '~> 3.0.0'
|
6
|
+
|
7
|
+
|
8
|
+
###### added manually ######
|
9
|
+
|
10
|
+
group :development do
|
11
|
+
gem 'rspec', '~> 2.8'
|
12
|
+
gem 'bundler', '~> 1.1'
|
13
|
+
gem 'jeweler', '~> 1.8'
|
14
|
+
|
15
|
+
gem 'guard-rspec'
|
16
|
+
end
|
17
|
+
|
18
|
+
group :development, :test do
|
19
|
+
gem 'bson_ext', :platforms => :ruby
|
20
|
+
|
21
|
+
gem 'rake'
|
22
|
+
# v0.4.1 doesn't support multiple group names
|
23
|
+
gem 'appraisal', :git => 'git://github.com/thoughtbot/appraisal.git', :ref => 'ad2aeb99649f6a78f78be5009fb50306f06eaa9f'
|
24
|
+
end
|
data/lib/mongoid/locker.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'locker', 'wrapper'))
|
2
|
+
|
1
3
|
module Mongoid
|
2
4
|
module Locker
|
3
5
|
module ClassMethods
|
@@ -48,6 +50,13 @@ module Mongoid
|
|
48
50
|
!!(self.locked_until && self.locked_until > Time.now)
|
49
51
|
end
|
50
52
|
|
53
|
+
# Returns whether the current instance has the lock or not.
|
54
|
+
#
|
55
|
+
# @return [Boolean] true if locked, false otherwise
|
56
|
+
def has_lock?
|
57
|
+
@has_lock && self.locked?
|
58
|
+
end
|
59
|
+
|
51
60
|
# Primary method of plugin: execute the provided code once the document has been successfully locked.
|
52
61
|
#
|
53
62
|
# @param [Hash] opts for the locking mechanism
|
@@ -55,11 +64,14 @@ module Mongoid
|
|
55
64
|
# @option opts [Boolean] :wait If the document is currently locked, wait until the lock expires and try again
|
56
65
|
# @return [void]
|
57
66
|
def with_lock opts={}, &block
|
58
|
-
|
67
|
+
# don't try to re-lock/unlock on recursive calls
|
68
|
+
had_lock = self.has_lock?
|
69
|
+
self.lock(opts) unless had_lock
|
70
|
+
|
59
71
|
begin
|
60
72
|
yield
|
61
73
|
ensure
|
62
|
-
self.unlock
|
74
|
+
self.unlock unless had_lock
|
63
75
|
end
|
64
76
|
end
|
65
77
|
|
@@ -67,14 +79,14 @@ module Mongoid
|
|
67
79
|
protected
|
68
80
|
|
69
81
|
def lock opts={}
|
70
|
-
coll = self.class.collection
|
71
82
|
time = Time.now
|
72
83
|
timeout = opts[:timeout] || self.class.lock_timeout
|
73
84
|
expiration = time + timeout
|
74
85
|
|
75
86
|
# lock the document atomically in the DB without persisting entire doc
|
76
|
-
|
77
|
-
|
87
|
+
locked = Mongoid::Locker::Wrapper.update(
|
88
|
+
self.class,
|
89
|
+
{
|
78
90
|
:_id => self.id,
|
79
91
|
'$or' => [
|
80
92
|
# not locked
|
@@ -83,7 +95,7 @@ module Mongoid
|
|
83
95
|
{:locked_until => {'$lte' => time}}
|
84
96
|
]
|
85
97
|
},
|
86
|
-
|
98
|
+
{
|
87
99
|
'$set' => {
|
88
100
|
:locked_at => time,
|
89
101
|
:locked_until => expiration
|
@@ -91,21 +103,17 @@ module Mongoid
|
|
91
103
|
}
|
92
104
|
)
|
93
105
|
|
94
|
-
if
|
95
|
-
#
|
106
|
+
if locked
|
107
|
+
# document successfully updated, meaning it was locked
|
96
108
|
self.locked_at = time
|
97
109
|
self.locked_until = expiration
|
110
|
+
@has_lock = true
|
98
111
|
else
|
99
112
|
# couldn't grab lock
|
100
113
|
|
101
|
-
|
102
|
-
:_id => self.id,
|
103
|
-
:locked_until => {'$exists' => true}
|
104
|
-
}
|
105
|
-
|
106
|
-
if opts[:wait] && existing = coll.find(existing_query, :limit => 1).first
|
114
|
+
if opts[:wait] && locked_until = Mongoid::Locker::Wrapper.locked_until(self)
|
107
115
|
# doc is locked - wait until it expires
|
108
|
-
wait_time =
|
116
|
+
wait_time = locked_until - Time.now
|
109
117
|
sleep wait_time if wait_time > 0
|
110
118
|
|
111
119
|
# only wait once
|
@@ -122,15 +130,20 @@ module Mongoid
|
|
122
130
|
|
123
131
|
def unlock
|
124
132
|
# unlock the document in the DB without persisting entire doc
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
133
|
+
Mongoid::Locker::Wrapper.update(
|
134
|
+
self.class,
|
135
|
+
{:_id => self.id},
|
136
|
+
{
|
137
|
+
'$set' => {
|
138
|
+
:locked_at => nil,
|
139
|
+
:locked_until => nil,
|
140
|
+
}
|
129
141
|
}
|
130
|
-
|
142
|
+
)
|
131
143
|
|
132
144
|
self.locked_at = nil
|
133
145
|
self.locked_until = nil
|
146
|
+
@has_lock = false
|
134
147
|
end
|
135
148
|
end
|
136
149
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Locker
|
3
|
+
# Normalizes queries between Mongoid 2 and 3.
|
4
|
+
module Wrapper
|
5
|
+
IS_OLD_MONGOID = Mongoid::VERSION.start_with? '2'
|
6
|
+
|
7
|
+
# Update the document for the provided Class matching the provided query with the provided setter.
|
8
|
+
#
|
9
|
+
# @param [Class] The model class
|
10
|
+
# @param [Hash] The Mongoid query
|
11
|
+
# @param [Hash] The Mongoid setter
|
12
|
+
# @return [Boolean] true if the document was successfully updated, false otherwise
|
13
|
+
def self.update klass, query, setter
|
14
|
+
if IS_OLD_MONGOID
|
15
|
+
error_obj = klass.collection.update(query, setter, :safe => true)
|
16
|
+
error_obj['n'] == 1
|
17
|
+
else
|
18
|
+
!!klass.where(query).find_and_modify(setter, :new => false)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Determine whether the provided document is locked in the database or not.
|
23
|
+
#
|
24
|
+
# @param [Class] The model instance
|
25
|
+
# @return [Time] The timestamp of when the document is locked until, nil if not locked.
|
26
|
+
def self.locked_until doc
|
27
|
+
existing_query = {
|
28
|
+
:_id => doc.id,
|
29
|
+
:locked_until => {'$exists' => true}
|
30
|
+
}
|
31
|
+
|
32
|
+
if IS_OLD_MONGOID
|
33
|
+
existing = doc.class.collection.find_one(existing_query, :fields => {:locked_until => 1})
|
34
|
+
existing ? existing['locked_until'] : nil
|
35
|
+
else
|
36
|
+
existing = doc.class.where(existing_query).limit(1).only(:locked_until).first
|
37
|
+
existing ? existing.locked_until : nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/mongoid-locker.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "mongoid-locker"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Aidan Feldman"]
|
12
|
-
s.date = "2012-
|
12
|
+
s.date = "2012-08-27"
|
13
13
|
s.description = "Allows multiple processes to operate on individual documents in MongoDB while ensuring that only one can act at a time."
|
14
14
|
s.email = "aidan.feldman@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -20,15 +20,20 @@ Gem::Specification.new do |s|
|
|
20
20
|
".document",
|
21
21
|
".rspec",
|
22
22
|
".travis.yml",
|
23
|
+
"Appraisals",
|
23
24
|
"CHANGELOG.md",
|
24
25
|
"Gemfile",
|
26
|
+
"Gemfile.lock",
|
25
27
|
"Guardfile",
|
26
28
|
"LICENSE.txt",
|
27
29
|
"README.md",
|
28
30
|
"Rakefile",
|
29
31
|
"VERSION",
|
32
|
+
"gemfiles/mongoid2.gemfile",
|
33
|
+
"gemfiles/mongoid3.gemfile",
|
30
34
|
"lib/mongoid-locker.rb",
|
31
35
|
"lib/mongoid/locker.rb",
|
36
|
+
"lib/mongoid/locker/wrapper.rb",
|
32
37
|
"mongoid-locker.gemspec",
|
33
38
|
"spec/database.yml",
|
34
39
|
"spec/mongoid-locker_spec.rb",
|
@@ -44,27 +49,33 @@ Gem::Specification.new do |s|
|
|
44
49
|
s.specification_version = 3
|
45
50
|
|
46
51
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
47
|
-
s.add_runtime_dependency(%q<mongoid>, ["
|
52
|
+
s.add_runtime_dependency(%q<mongoid>, ["<= 3.1", ">= 2.4"])
|
48
53
|
s.add_development_dependency(%q<rspec>, ["~> 2.8"])
|
49
54
|
s.add_development_dependency(%q<bundler>, ["~> 1.1"])
|
50
55
|
s.add_development_dependency(%q<jeweler>, ["~> 1.8"])
|
51
56
|
s.add_development_dependency(%q<guard-rspec>, [">= 0"])
|
52
57
|
s.add_development_dependency(%q<bson_ext>, [">= 0"])
|
58
|
+
s.add_development_dependency(%q<rake>, [">= 0"])
|
59
|
+
s.add_development_dependency(%q<appraisal>, [">= 0"])
|
53
60
|
else
|
54
|
-
s.add_dependency(%q<mongoid>, ["
|
61
|
+
s.add_dependency(%q<mongoid>, ["<= 3.1", ">= 2.4"])
|
55
62
|
s.add_dependency(%q<rspec>, ["~> 2.8"])
|
56
63
|
s.add_dependency(%q<bundler>, ["~> 1.1"])
|
57
64
|
s.add_dependency(%q<jeweler>, ["~> 1.8"])
|
58
65
|
s.add_dependency(%q<guard-rspec>, [">= 0"])
|
59
66
|
s.add_dependency(%q<bson_ext>, [">= 0"])
|
67
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
68
|
+
s.add_dependency(%q<appraisal>, [">= 0"])
|
60
69
|
end
|
61
70
|
else
|
62
|
-
s.add_dependency(%q<mongoid>, ["
|
71
|
+
s.add_dependency(%q<mongoid>, ["<= 3.1", ">= 2.4"])
|
63
72
|
s.add_dependency(%q<rspec>, ["~> 2.8"])
|
64
73
|
s.add_dependency(%q<bundler>, ["~> 1.1"])
|
65
74
|
s.add_dependency(%q<jeweler>, ["~> 1.8"])
|
66
75
|
s.add_dependency(%q<guard-rspec>, [">= 0"])
|
67
76
|
s.add_dependency(%q<bson_ext>, [">= 0"])
|
77
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
78
|
+
s.add_dependency(%q<appraisal>, [">= 0"])
|
68
79
|
end
|
69
80
|
end
|
70
81
|
|
data/spec/database.yml
CHANGED
data/spec/mongoid-locker_spec.rb
CHANGED
@@ -25,7 +25,40 @@ describe Mongoid::Locker do
|
|
25
25
|
|
26
26
|
describe "#locked?" do
|
27
27
|
it "shouldn't be locked when created" do
|
28
|
-
@user.
|
28
|
+
@user.locked?.should be_false
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should be true when locked" do
|
32
|
+
@user.with_lock do
|
33
|
+
@user.locked?.should be_true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should respect the expiration" do
|
38
|
+
User.timeout_lock_after 1
|
39
|
+
|
40
|
+
@user.with_lock do
|
41
|
+
sleep 2
|
42
|
+
@user.locked?.should be_false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should be true for a different instance" do
|
47
|
+
@user.with_lock do
|
48
|
+
User.first.locked?.should be_true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#has_lock?" do
|
54
|
+
it "shouldn't be has_lock when created" do
|
55
|
+
@user.has_lock?.should be_false
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should be true when has_lock" do
|
59
|
+
@user.with_lock do
|
60
|
+
@user.has_lock?.should be_true
|
61
|
+
end
|
29
62
|
end
|
30
63
|
|
31
64
|
it "should respect the expiration" do
|
@@ -33,7 +66,13 @@ describe Mongoid::Locker do
|
|
33
66
|
|
34
67
|
@user.with_lock do
|
35
68
|
sleep 2
|
36
|
-
@user.
|
69
|
+
@user.has_lock?.should be_false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should be false for a different instance" do
|
74
|
+
@user.with_lock do
|
75
|
+
User.first.has_lock?.should be_false
|
37
76
|
end
|
38
77
|
end
|
39
78
|
end
|
@@ -80,6 +119,16 @@ describe Mongoid::Locker do
|
|
80
119
|
end
|
81
120
|
end
|
82
121
|
|
122
|
+
it "should handle recursive calls" do
|
123
|
+
@user.with_lock do
|
124
|
+
@user.with_lock do
|
125
|
+
@user.account_balance = 10
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
@user.account_balance.should eq(10)
|
130
|
+
end
|
131
|
+
|
83
132
|
it "should wait until the lock times out, if desired" do
|
84
133
|
User.timeout_lock_after 1
|
85
134
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-locker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,14 +9,17 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-08-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mongoid
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - <=
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.1'
|
22
|
+
- - ! '>='
|
20
23
|
- !ruby/object:Gem::Version
|
21
24
|
version: '2.4'
|
22
25
|
type: :runtime
|
@@ -24,7 +27,10 @@ dependencies:
|
|
24
27
|
version_requirements: !ruby/object:Gem::Requirement
|
25
28
|
none: false
|
26
29
|
requirements:
|
27
|
-
- -
|
30
|
+
- - <=
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.1'
|
33
|
+
- - ! '>='
|
28
34
|
- !ruby/object:Gem::Version
|
29
35
|
version: '2.4'
|
30
36
|
- !ruby/object:Gem::Dependency
|
@@ -107,6 +113,38 @@ dependencies:
|
|
107
113
|
- - ! '>='
|
108
114
|
- !ruby/object:Gem::Version
|
109
115
|
version: '0'
|
116
|
+
- !ruby/object:Gem::Dependency
|
117
|
+
name: rake
|
118
|
+
requirement: !ruby/object:Gem::Requirement
|
119
|
+
none: false
|
120
|
+
requirements:
|
121
|
+
- - ! '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
type: :development
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ! '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
- !ruby/object:Gem::Dependency
|
133
|
+
name: appraisal
|
134
|
+
requirement: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ! '>='
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
type: :development
|
141
|
+
prerelease: false
|
142
|
+
version_requirements: !ruby/object:Gem::Requirement
|
143
|
+
none: false
|
144
|
+
requirements:
|
145
|
+
- - ! '>='
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
110
148
|
description: Allows multiple processes to operate on individual documents in MongoDB
|
111
149
|
while ensuring that only one can act at a time.
|
112
150
|
email: aidan.feldman@gmail.com
|
@@ -119,15 +157,20 @@ files:
|
|
119
157
|
- .document
|
120
158
|
- .rspec
|
121
159
|
- .travis.yml
|
160
|
+
- Appraisals
|
122
161
|
- CHANGELOG.md
|
123
162
|
- Gemfile
|
163
|
+
- Gemfile.lock
|
124
164
|
- Guardfile
|
125
165
|
- LICENSE.txt
|
126
166
|
- README.md
|
127
167
|
- Rakefile
|
128
168
|
- VERSION
|
169
|
+
- gemfiles/mongoid2.gemfile
|
170
|
+
- gemfiles/mongoid3.gemfile
|
129
171
|
- lib/mongoid-locker.rb
|
130
172
|
- lib/mongoid/locker.rb
|
173
|
+
- lib/mongoid/locker/wrapper.rb
|
131
174
|
- mongoid-locker.gemspec
|
132
175
|
- spec/database.yml
|
133
176
|
- spec/mongoid-locker_spec.rb
|
@@ -147,7 +190,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
147
190
|
version: '0'
|
148
191
|
segments:
|
149
192
|
- 0
|
150
|
-
hash:
|
193
|
+
hash: 2610862896755729046
|
151
194
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
195
|
none: false
|
153
196
|
requirements:
|