mongoid-locker 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,12 +10,12 @@ module Mongoid
10
10
  # @param [Hash] The Mongoid query
11
11
  # @param [Hash] The Mongoid setter
12
12
  # @return [Boolean] true if the document was successfully updated, false otherwise
13
- def self.update klass, query, setter
13
+ def self.update(klass, query, setter)
14
14
  error_obj =
15
15
  if IS_OLD_MONGOID
16
- klass.collection.update(query, setter, :safe => true)
16
+ klass.collection.update(query, setter, safe: true)
17
17
  else
18
- klass.with(:safe => true).collection.find(query).update(setter)
18
+ klass.with(safe: true).collection.find(query).update(setter)
19
19
  end
20
20
 
21
21
  error_obj['n'] == 1
@@ -25,14 +25,14 @@ module Mongoid
25
25
  #
26
26
  # @param [Class] The model instance
27
27
  # @return [Time] The timestamp of when the document is locked until, nil if not locked.
28
- def self.locked_until doc
28
+ def self.locked_until(doc)
29
29
  existing_query = {
30
- :_id => doc.id,
31
- :locked_until => {'$exists' => true}
30
+ _id: doc.id,
31
+ locked_until: { '$exists' => true }
32
32
  }
33
33
 
34
34
  if IS_OLD_MONGOID
35
- existing = doc.class.collection.find_one(existing_query, :fields => {:locked_until => 1})
35
+ existing = doc.class.collection.find_one(existing_query, fields: { locked_until: 1 })
36
36
  existing ? existing['locked_until'] : nil
37
37
  else
38
38
  existing = doc.class.where(existing_query).limit(1).only(:locked_until).first
@@ -2,14 +2,15 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
+ # stub: mongoid-locker 0.3.0 ruby lib
5
6
 
6
7
  Gem::Specification.new do |s|
7
8
  s.name = "mongoid-locker"
8
- s.version = "0.2.1"
9
+ s.version = "0.3.0"
9
10
 
10
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
12
  s.authors = ["Aidan Feldman"]
12
- s.date = "2012-11-28"
13
+ s.date = "2014-07-01"
13
14
  s.description = "Allows multiple processes to operate on individual documents in MongoDB while ensuring that only one can act at a time."
14
15
  s.email = "aidan.feldman@gmail.com"
15
16
  s.extra_rdoc_files = [
@@ -19,11 +20,11 @@ Gem::Specification.new do |s|
19
20
  s.files = [
20
21
  ".document",
21
22
  ".rspec",
23
+ ".rubocop.yml",
22
24
  ".travis.yml",
23
- "Appraisals",
24
25
  "CHANGELOG.md",
26
+ "CONTRIBUTING.md",
25
27
  "Gemfile",
26
- "Gemfile.lock",
27
28
  "Guardfile",
28
29
  "LICENSE.txt",
29
30
  "README.md",
@@ -35,53 +36,53 @@ Gem::Specification.new do |s|
35
36
  "demo/instagram.png",
36
37
  "demo/showoff.css",
37
38
  "demo/showoff.md",
38
- "gemfiles/mongoid2.gemfile",
39
- "gemfiles/mongoid3.gemfile",
40
39
  "lib/mongoid-locker.rb",
41
40
  "lib/mongoid/locker.rb",
42
41
  "lib/mongoid/locker/wrapper.rb",
43
42
  "mongoid-locker.gemspec",
44
- "spec/database.yml",
43
+ "spec/database2.yml",
44
+ "spec/database3.yml",
45
+ "spec/database4.yml",
45
46
  "spec/mongoid-locker_spec.rb",
46
47
  "spec/spec_helper.rb"
47
48
  ]
48
49
  s.homepage = "http://github.com/afeld/mongoid-locker"
49
50
  s.licenses = ["MIT"]
50
51
  s.require_paths = ["lib"]
51
- s.rubygems_version = "1.8.24"
52
+ s.rubygems_version = "2.1.11"
52
53
  s.summary = "Document-level locking for MongoDB via Mongoid"
53
54
 
54
55
  if s.respond_to? :specification_version then
55
- s.specification_version = 3
56
+ s.specification_version = 4
56
57
 
57
58
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
58
- s.add_runtime_dependency(%q<mongoid>, ["<= 3.1", ">= 2.4"])
59
- s.add_development_dependency(%q<rspec>, ["~> 2.8"])
59
+ s.add_runtime_dependency(%q<mongoid>, ["~> 4.0"])
60
+ s.add_development_dependency(%q<rspec>, ["~> 3.0"])
60
61
  s.add_development_dependency(%q<bundler>, ["~> 1.1"])
61
62
  s.add_development_dependency(%q<jeweler>, ["~> 1.8"])
62
63
  s.add_development_dependency(%q<guard-rspec>, [">= 0"])
63
- s.add_development_dependency(%q<bson_ext>, [">= 0"])
64
+ s.add_development_dependency(%q<rb-fsevent>, ["~> 0.9.1"])
64
65
  s.add_development_dependency(%q<rake>, [">= 0"])
65
- s.add_development_dependency(%q<appraisal>, [">= 0"])
66
+ s.add_development_dependency(%q<rubocop>, ["= 0.24.0"])
66
67
  else
67
- s.add_dependency(%q<mongoid>, ["<= 3.1", ">= 2.4"])
68
- s.add_dependency(%q<rspec>, ["~> 2.8"])
68
+ s.add_dependency(%q<mongoid>, ["~> 4.0"])
69
+ s.add_dependency(%q<rspec>, ["~> 3.0"])
69
70
  s.add_dependency(%q<bundler>, ["~> 1.1"])
70
71
  s.add_dependency(%q<jeweler>, ["~> 1.8"])
71
72
  s.add_dependency(%q<guard-rspec>, [">= 0"])
72
- s.add_dependency(%q<bson_ext>, [">= 0"])
73
+ s.add_dependency(%q<rb-fsevent>, ["~> 0.9.1"])
73
74
  s.add_dependency(%q<rake>, [">= 0"])
74
- s.add_dependency(%q<appraisal>, [">= 0"])
75
+ s.add_dependency(%q<rubocop>, ["= 0.24.0"])
75
76
  end
76
77
  else
77
- s.add_dependency(%q<mongoid>, ["<= 3.1", ">= 2.4"])
78
- s.add_dependency(%q<rspec>, ["~> 2.8"])
78
+ s.add_dependency(%q<mongoid>, ["~> 4.0"])
79
+ s.add_dependency(%q<rspec>, ["~> 3.0"])
79
80
  s.add_dependency(%q<bundler>, ["~> 1.1"])
80
81
  s.add_dependency(%q<jeweler>, ["~> 1.8"])
81
82
  s.add_dependency(%q<guard-rspec>, [">= 0"])
82
- s.add_dependency(%q<bson_ext>, [">= 0"])
83
+ s.add_dependency(%q<rb-fsevent>, ["~> 0.9.1"])
83
84
  s.add_dependency(%q<rake>, [">= 0"])
84
- s.add_dependency(%q<appraisal>, [">= 0"])
85
+ s.add_dependency(%q<rubocop>, ["= 0.24.0"])
85
86
  end
86
87
  end
87
88
 
@@ -0,0 +1,4 @@
1
+ test:
2
+ # for Mongoid 2
3
+ host: localhost
4
+ database: mongoid_locker_test
@@ -1,8 +1,4 @@
1
1
  test:
2
- # for Mongoid 2
3
- host: localhost
4
- database: mongoid_locker_test
5
-
6
2
  # for Mongoid 3
7
3
  sessions:
8
4
  default:
@@ -0,0 +1,7 @@
1
+ test:
2
+ # for Mongoid 4
3
+ sessions:
4
+ default:
5
+ database: mongoid_locker_test
6
+ hosts:
7
+ - localhost:27017
@@ -1,7 +1,7 @@
1
1
  require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
 
3
3
  describe Mongoid::Locker do
4
- def remove_class klass
4
+ def remove_class(klass)
5
5
  Object.send :remove_const, klass.to_s.to_sym
6
6
  end
7
7
 
@@ -11,10 +11,10 @@ describe Mongoid::Locker do
11
11
  include Mongoid::Document
12
12
  include Mongoid::Locker
13
13
 
14
- field :account_balance, :type => Integer # easier to test than Float
14
+ field :account_balance, type: Integer # easier to test than Float
15
15
  end
16
16
 
17
- @user = User.create! :account_balance => 20
17
+ @user = User.create! account_balance: 20
18
18
  end
19
19
 
20
20
  after do
@@ -22,70 +22,69 @@ describe Mongoid::Locker do
22
22
  remove_class User
23
23
  end
24
24
 
25
-
26
- describe "#locked?" do
25
+ describe '#locked?' do
27
26
  it "shouldn't be locked when created" do
28
- @user.locked?.should be_false
27
+ expect(@user.locked?).to be false
29
28
  end
30
29
 
31
- it "should be true when locked" do
30
+ it 'should be true when locked' do
32
31
  @user.with_lock do
33
- @user.locked?.should be_true
32
+ expect(@user.locked?).to be true
34
33
  end
35
34
  end
36
35
 
37
- it "should respect the expiration" do
36
+ it 'should respect the expiration' do
38
37
  User.timeout_lock_after 1
39
38
 
40
39
  @user.with_lock do
41
40
  sleep 2
42
- @user.locked?.should be_false
41
+ expect(@user.locked?).to be false
43
42
  end
44
43
  end
45
44
 
46
- it "should be true for a different instance" do
45
+ it 'should be true for a different instance' do
47
46
  @user.with_lock do
48
- User.first.locked?.should be_true
47
+ expect(User.first.locked?).to be true
49
48
  end
50
49
  end
51
50
  end
52
51
 
53
- describe "#has_lock?" do
52
+ describe '#has_lock?' do
54
53
  it "shouldn't be has_lock when created" do
55
- @user.has_lock?.should be_false
54
+ expect(@user.has_lock?).to be false
56
55
  end
57
56
 
58
- it "should be true when has_lock" do
57
+ it 'should be true when has_lock' do
59
58
  @user.with_lock do
60
- @user.has_lock?.should be_true
59
+ expect(@user.has_lock?).to be true
61
60
  end
62
61
  end
63
62
 
64
- it "should respect the expiration" do
63
+ it 'should respect the expiration' do
65
64
  User.timeout_lock_after 1
66
65
 
67
66
  @user.with_lock do
68
67
  sleep 2
69
- @user.has_lock?.should be_false
68
+ expect(@user.has_lock?).to be false
70
69
  end
71
70
  end
72
71
 
73
- it "should be false for a different instance" do
72
+ it 'should be false for a different instance' do
74
73
  @user.with_lock do
75
- User.first.has_lock?.should be_false
74
+ expect(User.first.has_lock?).to be false
76
75
  end
77
76
  end
78
77
  end
79
78
 
80
- describe "#with_lock" do
81
- it "should lock and unlock the user" do
79
+ describe '#with_lock' do
80
+ it 'should lock and unlock the user' do
82
81
  @user.with_lock do
83
- @user.should be_locked
84
- User.first.should be_locked
82
+ expect(@user).to be_locked
83
+ expect(User.first).to be_locked
85
84
  end
86
85
 
87
- @user.should_not be_locked
88
- @user.reload.should_not be_locked
86
+ expect(@user).to_not be_locked
87
+ expect(@user.reload).to_not be_locked
89
88
  end
90
89
 
91
90
  it "shouldn't save the full document" do
@@ -93,21 +92,21 @@ describe Mongoid::Locker do
93
92
  @user.account_balance = 10
94
93
  end
95
94
 
96
- @user.account_balance.should eq(10)
97
- User.first.account_balance.should eq(20)
95
+ expect(@user.account_balance).to eq(10)
96
+ expect(User.first.account_balance).to eq(20)
98
97
  end
99
98
 
100
- it "should handle errors gracefully" do
99
+ it 'should handle errors gracefully' do
101
100
  expect {
102
101
  @user.with_lock do
103
- raise "booyah!"
102
+ fail 'booyah!'
104
103
  end
105
104
  }.to raise_error
106
105
 
107
- @user.reload.should_not be_locked
106
+ expect(@user.reload).to_not be_locked
108
107
  end
109
108
 
110
- it "should complain if trying to lock locked doc" do
109
+ it 'should complain if trying to lock locked doc' do
111
110
  @user.with_lock do
112
111
  user_dup = User.first
113
112
 
@@ -115,45 +114,105 @@ describe Mongoid::Locker do
115
114
  user_dup.with_lock do
116
115
  fail "shouldn't get the lock"
117
116
  end
118
- }.to raise_error(Mongoid::LockError)
117
+ }.to raise_error(Mongoid::Locker::LockError)
119
118
  end
120
119
  end
121
120
 
122
- it "should handle recursive calls" do
121
+ it 'should handle recursive calls' do
123
122
  @user.with_lock do
124
123
  @user.with_lock do
125
124
  @user.account_balance = 10
126
125
  end
127
126
  end
128
127
 
129
- @user.account_balance.should eq(10)
128
+ expect(@user.account_balance).to eq(10)
130
129
  end
131
130
 
132
- it "should wait until the lock times out, if desired" do
131
+ it 'should wait until the lock times out, if desired' do
133
132
  User.timeout_lock_after 1
134
133
 
135
134
  @user.with_lock do
136
135
  user_dup = User.first
137
136
 
138
- user_dup.with_lock :wait => true do
137
+ user_dup.with_lock wait: true do
139
138
  user_dup.account_balance = 10
140
139
  user_dup.save!
141
140
  end
142
141
  end
143
142
 
144
- @user.reload.account_balance.should eq(10)
143
+ expect(@user.reload.account_balance).to eq(10)
144
+ end
145
+
146
+ it 'should, by default, reload the row after acquiring the lock' do
147
+ expect(@user).to receive(:reload)
148
+ @user.with_lock do
149
+ # no-op
150
+ end
151
+ end
152
+
153
+ it 'should allow override of the default reload behavior' do
154
+ expect(@user).to_not receive(:reload)
155
+ @user.with_lock reload: false do
156
+ # no-op
157
+ end
158
+ end
159
+
160
+ it 'should, by default, not retry' do
161
+ expect(@user).to receive(:acquire_lock).once.and_return(true)
162
+ @user.with_lock do
163
+ user_dup = User.first
164
+
165
+ user_dup.with_lock do
166
+ # no-op
167
+ end
168
+ end
169
+ end
170
+
171
+ it 'should retry the number of times given, if desired' do
172
+ allow(@user).to receive(:acquire_lock).and_return(false)
173
+ allow(Mongoid::Locker::Wrapper).to receive(:locked_until).and_return(Time.now)
174
+
175
+ expect(@user).to receive(:acquire_lock).exactly(6).times
176
+ expect {
177
+ @user.with_lock retries: 5 do
178
+ # no-op
179
+ end
180
+ }.to raise_error(Mongoid::Locker::LockError)
181
+ end
182
+
183
+ it 'should, by default, when retrying, sleep until the lock expires' do
184
+ allow(@user).to receive(:acquire_lock).and_return(false)
185
+ allow(Mongoid::Locker::Wrapper).to receive(:locked_until).and_return(Time.now + 5.seconds)
186
+ allow(@user).to receive(:sleep) { |time| expect(time).to be_within(0.1).of(5) }
187
+
188
+ expect {
189
+ @user.with_lock retries: 1 do
190
+ # no-op
191
+ end
192
+ }.to raise_error(Mongoid::Locker::LockError)
193
+ end
194
+
195
+ it 'should sleep for the time given, if desired' do
196
+ allow(@user).to receive(:acquire_lock).and_return(false)
197
+ allow(@user).to receive(:sleep) { |time| expect(time).to be_within(0.1).of(3) }
198
+
199
+ expect {
200
+ @user.with_lock(retries: 1, retry_sleep: 3) do
201
+ # no-op
202
+ end
203
+ }.to raise_error(Mongoid::Locker::LockError)
145
204
  end
146
205
 
147
- it "should override the default timeout" do
206
+ it 'should override the default timeout' do
148
207
  User.timeout_lock_after 1
149
208
 
150
209
  expiration = (Time.now + 3).to_i
151
- @user.with_lock :timeout => 3 do
152
- @user.locked_until.to_i.should eq(expiration)
210
+ @user.with_lock timeout: 3 do
211
+ expect(@user.locked_until.to_i).to eq(expiration)
153
212
  end
154
213
  end
155
214
 
156
- it "should reload the document if it needs to wait for a lock" do
215
+ it 'should reload the document if it needs to wait for a lock' do
157
216
  User.timeout_lock_after 1
158
217
 
159
218
  @user.with_lock do
@@ -162,33 +221,33 @@ describe Mongoid::Locker do
162
221
  @user.account_balance = 10
163
222
  @user.save!
164
223
 
165
- user_dup.account_balance.should eq(20)
166
- user_dup.with_lock :wait => true do
167
- user_dup.account_balance.should eq(10)
224
+ expect(user_dup.account_balance).to eq(20)
225
+ user_dup.with_lock wait: true do
226
+ expect(user_dup.account_balance).to eq(10)
168
227
  end
169
228
  end
170
229
  end
171
230
 
172
- it "should succeed for subclasses" do
231
+ it 'should succeed for subclasses' do
173
232
  class Admin < User
174
233
  end
175
234
 
176
235
  admin = Admin.create!
177
236
 
178
237
  admin.with_lock do
179
- admin.should be_locked
180
- Admin.first.should be_locked
238
+ expect(admin).to be_locked
239
+ expect(Admin.first).to be_locked
181
240
  end
182
241
 
183
- admin.should_not be_locked
184
- admin.reload.should_not be_locked
242
+ expect(admin).to_not be_locked
243
+ expect(admin.reload).to_not be_locked
185
244
 
186
245
  remove_class Admin
187
246
  end
188
247
  end
189
248
 
190
- describe ".timeout_lock_after" do
191
- it "should ignore the lock if it has timed out" do
249
+ describe '.timeout_lock_after' do
250
+ it 'should ignore the lock if it has timed out' do
192
251
  User.timeout_lock_after 1
193
252
 
194
253
  @user.with_lock do
@@ -201,10 +260,10 @@ describe Mongoid::Locker do
201
260
  end
202
261
  end
203
262
 
204
- @user.reload.account_balance.should eq(10)
263
+ expect(@user.reload.account_balance).to eq(10)
205
264
  end
206
265
 
207
- it "should be independent for different classes" do
266
+ it 'should be independent for different classes' do
208
267
  class Account
209
268
  include Mongoid::Document
210
269
  include Mongoid::Locker
@@ -213,28 +272,28 @@ describe Mongoid::Locker do
213
272
  User.timeout_lock_after 1
214
273
  Account.timeout_lock_after 2
215
274
 
216
- User.lock_timeout.should eq(1)
275
+ expect(User.lock_timeout).to eq(1)
217
276
 
218
277
  remove_class Account
219
278
  end
220
279
  end
221
280
 
222
- describe ".locked" do
223
- it "should return the locked documents" do
224
- user2 = User.create!
281
+ describe '.locked' do
282
+ it 'should return the locked documents' do
283
+ User.create!
225
284
 
226
285
  @user.with_lock do
227
- User.locked.to_a.should eq([@user])
286
+ expect(User.locked.to_a).to eq([@user])
228
287
  end
229
288
  end
230
289
  end
231
290
 
232
- describe ".unlocked" do
233
- it "should return the unlocked documents" do
291
+ describe '.unlocked' do
292
+ it 'should return the unlocked documents' do
234
293
  user2 = User.create!
235
294
 
236
295
  @user.with_lock do
237
- User.unlocked.to_a.should eq([user2])
296
+ expect(User.unlocked.to_a).to eq([user2])
238
297
  end
239
298
  end
240
299
  end