mongo-lock 1.1.4 → 1.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.
Files changed (39) hide show
  1. checksums.yaml +8 -8
  2. data/Gemfile.lock +41 -38
  3. data/README.md +7 -4
  4. data/lib/mongo-lock.rb +22 -37
  5. data/lib/mongo-lock/configuration.rb +38 -4
  6. data/lib/mongo-lock/drivers/base.rb +41 -0
  7. data/lib/mongo-lock/drivers/mongo.rb +99 -0
  8. data/lib/mongo-lock/drivers/moped.rb +62 -0
  9. data/lib/mongo-lock/send_with_raise_methods.rb +28 -0
  10. data/lib/mongo-lock/version.rb +1 -1
  11. data/mongo-lock.gemspec +4 -3
  12. data/spec/configuration_spec.rb +66 -0
  13. data/spec/configure_spec.rb +8 -2
  14. data/spec/examples/acquire_example.rb +219 -0
  15. data/spec/examples/acquired_example.rb +54 -0
  16. data/spec/examples/available_example.rb +70 -0
  17. data/spec/examples/clear_expired_example.rb +100 -0
  18. data/spec/examples/ensure_indexes_example.rb +38 -0
  19. data/spec/examples/expired_example.rb +41 -0
  20. data/spec/examples/extend_by_example.rb +137 -0
  21. data/spec/examples/release_all_example.rb +117 -0
  22. data/spec/examples/release_example.rb +166 -0
  23. data/spec/initialise_spec.rb +2 -0
  24. data/spec/mongo_driver_spec.rb +22 -0
  25. data/spec/moped_driver_spec.rb +22 -0
  26. data/spec/rake_spec.rb +1 -1
  27. data/spec/spec_helper.rb +2 -7
  28. data/spec/support/mongo_helper.rb +41 -0
  29. metadata +58 -23
  30. data/lib/mongo-lock/mongo_queries.rb +0 -97
  31. data/spec/acquire_spec.rb +0 -217
  32. data/spec/acquired_spec.rb +0 -53
  33. data/spec/available_spec.rb +0 -68
  34. data/spec/clear_expired_spec.rb +0 -98
  35. data/spec/ensure_indexes_spec.rb +0 -34
  36. data/spec/expired_spec.rb +0 -39
  37. data/spec/extend_by_spec.rb +0 -135
  38. data/spec/release_all_spec.rb +0 -115
  39. data/spec/release_spec.rb +0 -164
@@ -1,97 +0,0 @@
1
- module Mongo
2
- class Lock
3
- class MongoQueries
4
-
5
- attr_accessor :lock
6
-
7
- def self.release_collection collection, owner=nil
8
- selector = if owner then { owner: owner } else {} end
9
- collection.remove(selector)
10
- end
11
-
12
- def self.ensure_indexes collection
13
- collection.create_index([
14
- ['key', Mongo::ASCENDING],
15
- ['owner', Mongo::ASCENDING],
16
- ['expires_at', Mongo::ASCENDING]
17
- ])
18
- collection.create_index([['ttl', Mongo::ASCENDING]],{ expireAfterSeconds: 0 })
19
- end
20
-
21
- def self.clear_expired collection
22
- collection.remove expires_at: { '$lt' => Time.now }
23
- end
24
-
25
- def initialize lock
26
- self.lock = lock
27
- end
28
-
29
- def key
30
- lock.key
31
- end
32
-
33
- def query
34
- {
35
- key: key,
36
- expires_at: { '$gt' => Time.now }
37
- }
38
- end
39
-
40
- def find_or_insert options
41
- options[:expire_at] = Time.now + options[:expire_in]
42
- options[:insert] = true
43
- find_and_modify options
44
- end
45
-
46
- def find_and_update time, options
47
- options[:expire_at] = lock.expires_at + time
48
- find_and_modify options
49
- end
50
-
51
- def find_and_modify options
52
- operation = options[:insert] ? '$setOnInsert' : '$set'
53
- existing_lock = lock.configuration.collection.find_and_modify({
54
- query: query,
55
- update: {
56
- operation => {
57
- key: key,
58
- owner: options[:owner],
59
- expires_at: options[:expire_at],
60
- ttl: options[:expire_at]
61
- }
62
- },
63
- upsert: !!options[:insert]
64
- })
65
-
66
- if existing_lock
67
- lock.expires_at = existing_lock['expires_at']
68
- else
69
- lock.expires_at = options[:expire_at]
70
- end
71
-
72
- existing_lock
73
- end
74
-
75
- def remove options
76
- lock.configuration.collection.remove key: key, owner: options[:owner]
77
- end
78
-
79
- def is_acquired?
80
- find_already_acquired.count > 0
81
- end
82
-
83
- def find_already_acquired
84
- lock.configuration.collection.find({
85
- key: key,
86
- owner: lock.configuration.owner,
87
- expires_at: { '$gt' => Time.now }
88
- })
89
- end
90
-
91
- def find_existing
92
- lock.configuration.collection.find(query).first
93
- end
94
-
95
- end
96
- end
97
- end
@@ -1,217 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Mongo::Lock do
4
-
5
- describe '.acquire' do
6
-
7
- it "creates and returns a new Mongo::Lock instance" do
8
- expect(Mongo::Lock.acquire 'my_lock').to be_a Mongo::Lock
9
- end
10
-
11
- it "calls #acquire to acquire the lock" do
12
- expect_any_instance_of(Mongo::Lock).to receive(:acquire)
13
- Mongo::Lock.acquire 'my_lock'
14
- end
15
-
16
- context "when options are provided" do
17
-
18
- it "passes them to the new lock" do
19
- lock = Mongo::Lock.acquire('my_lock', { limit: 3 })
20
- expect(lock.configuration.limit).to be 3
21
- end
22
-
23
- end
24
-
25
- context "when a block is provided" do
26
-
27
- it "passes it to the new lock" do
28
- block = Proc.new { |lock| }
29
- expect_any_instance_of(Mongo::Lock).to receive(:acquire).with( &block)
30
- lock = Mongo::Lock.acquire('my_lock', { limit: 3 }, &block)
31
- end
32
-
33
- end
34
-
35
- end
36
-
37
- describe '#acquire' do
38
-
39
- let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence' }
40
-
41
- context "when lock is available" do
42
-
43
- it "acquires the lock" do
44
- lock.acquire
45
- expect(my_collection.find(key: 'my_lock').count).to be 1
46
- end
47
-
48
- it "sets the lock to expire" do
49
- lock.acquire
50
- expect(my_collection.find(key: 'my_lock').first['expires_at']).to be_within(1.second).of(10.seconds.from_now)
51
- expect(my_collection.find(key: 'my_lock').first['ttl']).to be_within(1.second).of(10.seconds.from_now)
52
- end
53
-
54
- it "returns true" do
55
- expect(lock.acquire).to be_true
56
- end
57
-
58
- end
59
-
60
- context "when the frequency option is a Proc" do
61
-
62
- let(:lock) { Mongo::Lock.new 'my_lock' }
63
-
64
- it "should call the Proc with the attempt number" do
65
- my_collection.insert key: 'my_lock', owner: 'tobie', expires_at: 10.seconds.from_now
66
- proc = Proc.new{ |x| x }
67
- expect(proc).to receive(:call).with(1).and_return(0.01)
68
- expect(proc).to receive(:call).with(2).and_return(0.01)
69
- expect(proc).to receive(:call).with(3).and_return(0.01)
70
- lock.acquire limit: 3, frequency: proc
71
- end
72
-
73
- end
74
-
75
- context "when the lock is unavailable" do
76
-
77
- it "retries until it can acquire it" do
78
- my_collection.insert key: 'my_lock', owner: 'tobie', expires_at: 0.1.seconds.from_now
79
- lock.acquire frequency: 0.01, timeout_in: 0.2, limit: 20
80
- expect(my_collection.find(key: 'my_lock', owner: 'spence').count).to be 1
81
- end
82
-
83
- end
84
-
85
- context "when the lock is already acquired but by the same owner" do
86
-
87
- before :each do
88
- my_collection.insert key: 'my_lock', owner: 'spence', expires_at: 10.minutes.from_now
89
- end
90
-
91
- it "doesn't create a new lock" do
92
- lock.acquire
93
- expect(my_collection.find(key: 'my_lock').count).to be 1
94
- end
95
-
96
- it "returns true" do
97
- expect(lock.acquire).to be_true
98
- end
99
-
100
- it "sets this instance as acquired" do
101
- lock.acquire
102
- expect(lock.instance_variable_get('@acquired')).to be_true
103
- end
104
-
105
- end
106
-
107
- context "when the lock cannot be acquired" do
108
-
109
- context "and acquisition timeout_in occurs" do
110
-
111
- let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence', timeout_in: 0.03, frequency: 0.01 }
112
-
113
- it "should return false" do
114
- my_collection.insert key: 'my_lock', owner: 'tobie', expires_at: 1.second.from_now
115
- expect(lock.acquire).to be_false
116
- end
117
-
118
- end
119
-
120
- context "and acquisition limit is exceeded" do
121
-
122
- let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence', timeout_in: 0.4, limit: 3, frequency: 0.01 }
123
-
124
- it "should return false" do
125
- my_collection.insert key: 'my_lock', owner: 'tobie', expires_at: 1.second.from_now
126
- expect(lock.acquire).to be_false
127
- end
128
-
129
- end
130
-
131
- end
132
-
133
- context "when the lock cannot be acquired and raise option is set to true" do
134
-
135
- context "and acquisition timeout_in occurs" do
136
-
137
- let(:lock) { Mongo::Lock.new 'my_lock', owner: 'tobie', timeout_in: 0.4, limit: 3, frequency: 0.01, raise: true }
138
-
139
- it "should raise Mongo::Lock::NotAcquiredError" do
140
- my_collection.insert key: 'my_lock', owner: 'spence', expires_at: 1.second.from_now
141
- expect{lock.acquire}.to raise_error Mongo::Lock::NotAcquiredError
142
- end
143
-
144
- end
145
-
146
- context "and acquisition limit is exceeded" do
147
-
148
- let(:lock) { Mongo::Lock.new 'my_lock', owner: 'tobie', timeout_in: 0.3, limit: 3, frequency: 0.01, raise: true }
149
-
150
- it "should raise Mongo::Lock::NotAcquiredError" do
151
- my_collection.insert key: 'my_lock', owner: 'spence', expires_at: 1.second.from_now
152
- expect{lock.acquire}.to raise_error Mongo::Lock::NotAcquiredError
153
- end
154
-
155
- end
156
-
157
- end
158
-
159
- context "when options are provided" do
160
-
161
- let(:lock) { Mongo::Lock.new 'my_lock', owner: 'tobie', timeout_in: 0.2, limit: 11, frequency: 0.01, raise: true }
162
-
163
- it "overrides the lock's" do
164
- my_collection.insert key: 'my_lock', owner: 'spence', expires_at: 1.second.from_now
165
- expect(lock.acquire timeout_in: 0.05, limit: 3, frequency: 0.02, raise: false).to be_false
166
- end
167
-
168
- end
169
-
170
- context "when a block is provided" do
171
-
172
- let(:lock) { Mongo::Lock.new 'my_lock', owner: 'tobie', timeout_in: 0.2, limit: 11, frequency: 0.01, raise: true }
173
-
174
- it "should acquire the lock" do
175
- lock.acquire do |lock|
176
- expect(Mongo::Lock.available? 'my_lock', owner: 'spence').to be_false
177
- end
178
- end
179
-
180
- it "should call the block" do
181
- expect{ |block| lock.acquire &block }.to yield_with_args lock
182
- end
183
-
184
- it "should release the lock" do
185
- lock.acquire do |lock|
186
- # Do something
187
- end
188
- expect(Mongo::Lock.available?('my_lock', owner: 'spence')).to be_true
189
- end
190
-
191
- end
192
-
193
- end
194
-
195
- describe '.acquire!' do
196
-
197
- let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence' }
198
-
199
- it "calls .acquire with raise errors option set to true" do
200
- expect(Mongo::Lock).to receive(:init_and_send).with('my_lock', { limit: 3 }, :acquire!)
201
- Mongo::Lock.acquire! 'my_lock', limit: 3
202
- end
203
-
204
- end
205
-
206
- describe '#acquire!' do
207
-
208
- let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence' }
209
-
210
- it "calls #acquire with raise errors option set to true" do
211
- expect(lock).to receive(:acquire).with({ limit: 3, raise: true })
212
- lock.acquire! limit: 3
213
- end
214
-
215
- end
216
-
217
- end
@@ -1,53 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Mongo::Lock do
4
-
5
- describe '#acquired?' do
6
-
7
- let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence', timeout_in: 0.01, frequency: 0.01 }
8
-
9
- context "when the lock has been acquired" do
10
-
11
- it "returns true" do
12
- lock.acquire
13
- expect(lock.acquired?).to be_true
14
- end
15
-
16
- end
17
-
18
- context "when the lock hasn't been acquired" do
19
-
20
- it "returns false" do
21
- my_collection.insert key: 'my_lock', owner: 'tobie', expires_at: 1.minute.from_now
22
- lock.acquire
23
- expect(lock.acquired?).to be_false
24
- end
25
-
26
- end
27
-
28
- context "when the lock was acquired but has since expired" do
29
-
30
- let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence', timeout_in: 0.01, frequency: 0.01, expire_in: 0.1 }
31
-
32
- it "returns false" do
33
- lock.acquire
34
- sleep 0.2
35
- expect(lock.acquired?).to be_false
36
- end
37
-
38
- end
39
-
40
- context "when the lock was acquired but has since been released" do
41
-
42
- it "returns false" do
43
- my_collection.insert key: 'my_lock', owner: 'tobie', expires_at: 1.minute.ago
44
- lock.acquire
45
- lock.release
46
- expect(lock.acquired?).to be_false
47
- end
48
-
49
- end
50
-
51
- end
52
-
53
- end
@@ -1,68 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Mongo::Lock do
4
-
5
- describe '.available?' do
6
-
7
- it "creates a new Mongo::Lock instance and returns whether it is available" do
8
- expect(Mongo::Lock.available? 'my_lock').to be_true
9
- end
10
-
11
- it "calls #available?" do
12
- expect_any_instance_of(Mongo::Lock).to receive(:available?)
13
- Mongo::Lock.available? 'my_lock'
14
- end
15
-
16
- context "when options are provided" do
17
-
18
- it "passes them to the new lock" do
19
- Mongo::Lock.acquire 'my_lock', { owner: 'spence' }
20
- expect(Mongo::Lock.available?('my_lock', { owner: 'spence' })).to be_true
21
- end
22
-
23
- end
24
-
25
- end
26
-
27
- describe '#available?' do
28
-
29
- let(:lock) { Mongo::Lock.new 'my_lock', owner: 'spence', timeout_in: 0.01, frequency: 0.01 }
30
-
31
- context "when the lock is available" do
32
-
33
- it "returns true" do
34
- expect(lock.available?).to be_true
35
- end
36
-
37
- end
38
-
39
- context "when the lock is expired" do
40
-
41
- it "returns true" do
42
- my_collection.insert key: 'my_lock', owner: 'tobie', expires_at: 1.minute.ago
43
- expect(lock.available?).to be_true
44
- end
45
-
46
- end
47
-
48
- context "when the lock is already acquired but by this owner" do
49
-
50
- it "returns true" do
51
- my_collection.insert key: 'my_lock', owner: 'spence', expires_at: 1.minute.from_now
52
- expect(lock.available?).to be_true
53
- end
54
-
55
- end
56
-
57
- context "when the lock is already acquired" do
58
-
59
- it "returns false" do
60
- my_collection.insert key: 'my_lock', owner: 'tobie', expires_at: 1.minute.from_now
61
- expect(lock.available?).to be_false
62
- end
63
-
64
- end
65
-
66
- end
67
-
68
- end
@@ -1,98 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Mongo::Lock do
4
-
5
- describe '.clear_expired' do
6
-
7
- before :each do
8
- Mongo::Lock.configure collections: { default: my_collection, other: other_collection }
9
- end
10
-
11
- let!(:locks) do
12
- my_collection.insert key: 'tobies_lock', owner: 'tobie', expires_at: 1.minute.from_now, ttl: 1.minute.from_now
13
- my_collection.insert key: 'spences_lock', owner: 'spence', expires_at: 1.minute.ago, ttl: 1.minute.ago
14
- other_collection.insert key: 'spences_lock', owner: 'spence', expires_at: 1.minute.ago, ttl: 1.minute.ago
15
- another_collection.insert key: 'spences_lock', owner: 'spence', expires_at: 1.minute.ago, ttl: 1.minute.ago
16
- end
17
-
18
- it "deletes expired locks in all reegistered collections" do
19
- Mongo::Lock.configure collections: { default: my_collection, other: other_collection }
20
- other_collection.insert owner: 'owner', key: 'my_lock', expires_at: 1.minute.from_now
21
- Mongo::Lock.clear_expired
22
- expect(my_collection.find().count).to be 1
23
- expect(other_collection.find().count).to be 1
24
- end
25
-
26
- context "when a collection is provided" do
27
-
28
- before do
29
- Mongo::Lock.clear_expired collection: other_collection
30
- end
31
-
32
- it "does release locks in that collection" do
33
- expect(other_collection.find({ key: 'spences_lock', owner: 'spence'}).count).to eql 0
34
- end
35
-
36
- it "doesn't release locks in other collections" do
37
- expect(my_collection.find({ key: 'spences_lock', owner: 'spence'}).count).to eql 1
38
- expect(my_collection.find({ key: 'tobies_lock', owner: 'tobie'}).count).to eql 1
39
- end
40
-
41
- end
42
-
43
- context "when a collection symbol is provided" do
44
-
45
- before do
46
- Mongo::Lock.clear_expired collection: :other
47
- end
48
-
49
- it "does release locks in that collection" do
50
- expect(other_collection.find({ key: 'spences_lock', owner: 'spence'}).count).to eql 0
51
- end
52
-
53
- it "doesn't release locks in other collections" do
54
- expect(my_collection.find({ key: 'spences_lock', owner: 'spence'}).count).to eql 1
55
- expect(my_collection.find({ key: 'tobies_lock', owner: 'tobie'}).count).to eql 1
56
- end
57
-
58
- end
59
-
60
- context "when collections are provided" do
61
-
62
- before do
63
- Mongo::Lock.clear_expired collections: [another_collection, other_collection]
64
- end
65
-
66
- it "does release locks in those collection" do
67
- expect(other_collection.find({ key: 'spences_lock', owner: 'spence'}).count).to eql 0
68
- expect(another_collection.find({ key: 'spences_lock', owner: 'spence'}).count).to eql 0
69
- end
70
-
71
- it "doesn't release locks in other collections" do
72
- expect(my_collection.find({ key: 'spences_lock', owner: 'spence'}).count).to eql 1
73
- expect(my_collection.find({ key: 'tobies_lock', owner: 'tobie'}).count).to eql 1
74
- end
75
-
76
- context "when collections is provided as a hash" do
77
-
78
- before do
79
- Mongo::Lock.clear_expired collections: { another_collection: another_collection, other_collection: other_collection }
80
- end
81
-
82
- it "does release locks in those collection" do
83
- expect(other_collection.find({ key: 'spences_lock', owner: 'spence'}).count).to eql 0
84
- expect(another_collection.find({ key: 'spences_lock', owner: 'spence'}).count).to eql 0
85
- end
86
-
87
- it "doesn't release locks in other collections" do
88
- expect(my_collection.find({ key: 'spences_lock', owner: 'spence'}).count).to eql 1
89
- expect(my_collection.find({ key: 'tobies_lock', owner: 'tobie'}).count).to eql 1
90
- end
91
-
92
- end
93
-
94
- end
95
-
96
- end
97
-
98
- end