mongoid-locker 0.2.1 → 0.3.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.
@@ -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