mongoid-locking 1.1.0 → 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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +11 -1
- data/Gemfile.lock +9 -11
- data/README.md +52 -4
- data/lib/mongoid/locking/association/embedded/batchable.rb +29 -0
- data/lib/mongoid/locking/retry.rb +62 -0
- data/lib/mongoid/locking/version.rb +1 -1
- data/lib/mongoid/locking.rb +6 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59b03918904c46ce2770150d4b8d20d2b25ab735e6409982e804a9dbab8c4231
|
4
|
+
data.tar.gz: 316a1a9851bccd6580aedd95a9e5089a7b5a2ce4f9f2bc2b07a1af4f9ff4a263
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc860e6b8d43e812c6b7df124f72e1319041e795006f9dfd2c845cf0ee53d474c20d3d2c50b7d12e10e9b0b4f2eeb4180be38e6baa304b4bef132c14fcd89c9a
|
7
|
+
data.tar.gz: d545996296a982692f906ed2aa9ccd490855c153c6b949186552814250454168c0c8d8147efc8d5f094fb2f617a0ebc8c30ff02d8f93600143f227972a9fc83b
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,14 @@
|
|
1
|
-
## [
|
1
|
+
## [1.2.0]
|
2
|
+
|
3
|
+
- Add: with_locking method [#6](https://github.com/fullhealthmedical/mongoid-locking/pull/6)
|
4
|
+
|
5
|
+
## [1.1.1]
|
6
|
+
|
7
|
+
- Fix: Fix update embedded association [#5](https://github.com/fullhealthmedical/mongoid-locking/pull/5)
|
8
|
+
|
9
|
+
## [1.1.0]
|
10
|
+
|
11
|
+
- Add: Support for Mongoid 7.3 [#3](https://github.com/fullhealthmedical/mongoid-locking/pull/3)
|
2
12
|
|
3
13
|
## [0.1.0] - 2022-08-03
|
4
14
|
|
data/Gemfile.lock
CHANGED
@@ -1,20 +1,19 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
mongoid-locking (1.
|
5
|
-
mongoid (~> 7.2
|
4
|
+
mongoid-locking (1.2.0)
|
5
|
+
mongoid (~> 7.2)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activemodel (
|
11
|
-
activesupport (=
|
12
|
-
activesupport (
|
10
|
+
activemodel (7.0.8)
|
11
|
+
activesupport (= 7.0.8)
|
12
|
+
activesupport (7.0.8)
|
13
13
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
14
14
|
i18n (>= 1.6, < 2)
|
15
15
|
minitest (>= 5.1)
|
16
16
|
tzinfo (~> 2.0)
|
17
|
-
zeitwerk (~> 2.3)
|
18
17
|
ast (2.4.2)
|
19
18
|
bson (4.15.0)
|
20
19
|
byebug (11.1.3)
|
@@ -24,10 +23,10 @@ GEM
|
|
24
23
|
concurrent-ruby (~> 1.0)
|
25
24
|
json (2.6.2)
|
26
25
|
minitest (5.20.0)
|
27
|
-
mongo (2.19.
|
26
|
+
mongo (2.19.3)
|
28
27
|
bson (>= 4.14.1, < 5.0.0)
|
29
|
-
mongoid (7.
|
30
|
-
activemodel (>= 5.1, <
|
28
|
+
mongoid (7.5.4)
|
29
|
+
activemodel (>= 5.1, < 7.1, != 7.0.0)
|
31
30
|
mongo (>= 2.10.5, < 3.0.0)
|
32
31
|
ruby2_keywords (~> 0.0.5)
|
33
32
|
parallel (1.22.1)
|
@@ -69,7 +68,6 @@ GEM
|
|
69
68
|
tzinfo (2.0.6)
|
70
69
|
concurrent-ruby (~> 1.0)
|
71
70
|
unicode-display_width (2.2.0)
|
72
|
-
zeitwerk (2.6.12)
|
73
71
|
|
74
72
|
PLATFORMS
|
75
73
|
arm64-darwin-21
|
@@ -77,7 +75,7 @@ PLATFORMS
|
|
77
75
|
|
78
76
|
DEPENDENCIES
|
79
77
|
byebug
|
80
|
-
mongoid (~> 7.2
|
78
|
+
mongoid (~> 7.2)
|
81
79
|
mongoid-locking!
|
82
80
|
rake (~> 13.0)
|
83
81
|
rspec
|
data/README.md
CHANGED
@@ -19,7 +19,7 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
19
19
|
|
20
20
|
- Include `Mongoid::Locking` module
|
21
21
|
|
22
|
-
```
|
22
|
+
```ruby
|
23
23
|
class Order
|
24
24
|
include Mongoid::Document
|
25
25
|
include Mongoid::Locking
|
@@ -28,16 +28,64 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
28
28
|
|
29
29
|
- Handle `Mongoid::StaleObjectError` when performing updates
|
30
30
|
|
31
|
-
```
|
31
|
+
```ruby
|
32
32
|
# ...
|
33
33
|
def update_order
|
34
|
-
|
34
|
+
Order.update(attributes)
|
35
35
|
rescue Mongoid::StaleObjectError => e
|
36
36
|
add_error("This order has been changed ...")
|
37
37
|
end
|
38
38
|
end
|
39
39
|
```
|
40
40
|
|
41
|
+
- Use `with_locking` to automatically handle `Mongoid::StaleObjectError`
|
42
|
+
|
43
|
+
By default, `with_locking` will retry the update 3 times in case of a
|
44
|
+
`Mongoid::StaleObjectError`.
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
def process_with_locking
|
48
|
+
Order.with_locking do
|
49
|
+
# Ensure the block is idempotent
|
50
|
+
# Reload object(s) within the block to get the latest changes
|
51
|
+
order.reload
|
52
|
+
# Your code here
|
53
|
+
# ...
|
54
|
+
end
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
Adjust the `max_retries` parameter to control the number of retry attempts in
|
59
|
+
case of a `Mongoid::StaleObjectError`.
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
# ...
|
63
|
+
def update_order
|
64
|
+
order.with_locking(max_retries: 2) do
|
65
|
+
order.update(attributes)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
- Use `with_locking` at the instance level to automatically reload the instance
|
72
|
+
on each retry
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
def process_with_locking
|
76
|
+
order.with_locking do
|
77
|
+
# The instance is automatically reloaded for each retry
|
78
|
+
# Your code here
|
79
|
+
# ...
|
80
|
+
end
|
81
|
+
end
|
82
|
+
````
|
83
|
+
|
84
|
+
|
85
|
+
The with_locking method at the instance level combines class-level locking with
|
86
|
+
automatic reloading on each retry. This ensures that the instance reflects the
|
87
|
+
latest changes, providing seamless control over optimistic locking.
|
88
|
+
|
41
89
|
## Development
|
42
90
|
|
43
91
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -62,4 +110,4 @@ Everyone interacting in the Mongoid::Locking project's codebases, issue trackers
|
|
62
110
|
| -------- | ------- |
|
63
111
|
| 0.1.2 | >= 6.0, < 7.2 |
|
64
112
|
| 1.0.0 | ~> 7.2.0 |
|
65
|
-
| 1.1.0 | ~> 7.2 |
|
113
|
+
| ~> 1.1.0 | ~> 7.2 |
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Locking
|
3
|
+
module Association
|
4
|
+
module Embedded
|
5
|
+
module Batchable # :nodoc:
|
6
|
+
# Get the selector for executing atomic operations on the collection.
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
#
|
10
|
+
# @example Get the selector.
|
11
|
+
# batchable.selector
|
12
|
+
#
|
13
|
+
# @return [ Hash ] The atomic selector.
|
14
|
+
#
|
15
|
+
# @since 3.0.0
|
16
|
+
#
|
17
|
+
# ---
|
18
|
+
#
|
19
|
+
# Mongoid memoizes the atomic selector, which is not compatible with
|
20
|
+
# Mongoid::Locking. For subsequent saves, the lock_version needs to be
|
21
|
+
# updated, so the atomic selector needs to be regenerated.
|
22
|
+
def selector
|
23
|
+
_base.atomic_selector
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Locking
|
3
|
+
##
|
4
|
+
# Gives the ability to retry a block of code a specified number of times
|
5
|
+
# when a Mongoid::StaleObjectError is raised.
|
6
|
+
module Retry
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
##
|
12
|
+
# Retries the block of code a specified number of times when a
|
13
|
+
# Mongoid::StaleObjectError is raised.
|
14
|
+
#
|
15
|
+
# This method will reload the document before each block execution.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# person = Person.find(existing.id)
|
19
|
+
# person.with_locking do
|
20
|
+
# person.update!(name: "Person 1 updated")
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# @param [ Integer ] max_retries The maximum number of times to retry
|
24
|
+
#
|
25
|
+
# @return [ Object ] The result of the block
|
26
|
+
def with_locking(max_retries: 3)
|
27
|
+
self.class.with_locking(max_retries: max_retries) do
|
28
|
+
reload
|
29
|
+
yield
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module ClassMethods # :nodoc:
|
34
|
+
##
|
35
|
+
# Retries the block of code a specified number of times when a
|
36
|
+
# Mongoid::StaleObjectError is raised.
|
37
|
+
#
|
38
|
+
# @example
|
39
|
+
# Person.with_locking do
|
40
|
+
# person = Person.find(existing.id)
|
41
|
+
# Person.update!(name: "Person 1 updated")
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# @param [ Integer ] max_retries The maximum number of times to retry
|
45
|
+
#
|
46
|
+
# @return [ Object ] The result of the block
|
47
|
+
def with_locking(max_retries: 3)
|
48
|
+
retries = 0
|
49
|
+
|
50
|
+
begin
|
51
|
+
yield
|
52
|
+
rescue Mongoid::StaleObjectError
|
53
|
+
raise if retries >= max_retries
|
54
|
+
|
55
|
+
retries += 1
|
56
|
+
retry
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/mongoid/locking.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "mongoid"
|
2
2
|
require_relative "locking/version"
|
3
3
|
require_relative "stale_object_error"
|
4
|
+
require_relative "locking/association/embedded/batchable"
|
4
5
|
require_relative "locking/contextual/atomic"
|
5
6
|
require_relative "locking/contextual/mongo"
|
6
7
|
require_relative "locking/selectable"
|
@@ -8,6 +9,7 @@ require_relative "locking/reloadable"
|
|
8
9
|
require_relative "locking/persistable/creatable"
|
9
10
|
require_relative "locking/persistable/updatable"
|
10
11
|
require_relative "locking/persistable"
|
12
|
+
require_relative "locking/retry"
|
11
13
|
|
12
14
|
module Mongoid
|
13
15
|
##
|
@@ -21,7 +23,7 @@ module Mongoid
|
|
21
23
|
|
22
24
|
base.include Mongoid::Locking::Selectable
|
23
25
|
base.include Mongoid::Locking::Reloadable
|
24
|
-
|
26
|
+
base.include Mongoid::Locking::Retry
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
@@ -30,5 +32,8 @@ end
|
|
30
32
|
Mongoid::Contextual::Mongo.prepend Mongoid::Locking::Contextual::Mongo
|
31
33
|
Mongoid::Contextual::Mongo.prepend Mongoid::Locking::Contextual::Atomic
|
32
34
|
|
35
|
+
# monkey patching for embedded documents
|
36
|
+
Mongoid::Association::Embedded::Batchable.prepend Mongoid::Locking::Association::Embedded::Batchable
|
37
|
+
|
33
38
|
# monkey patching for document updates
|
34
39
|
Mongoid::Persistable.prepend Mongoid::Locking::Persistable
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-locking
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rodrigo RA
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-11
|
11
|
+
date: 2023-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mongoid
|
@@ -114,12 +114,14 @@ files:
|
|
114
114
|
- gemfiles/mongoid7_2.gemfile
|
115
115
|
- gemfiles/mongoid7_3.gemfile
|
116
116
|
- lib/mongoid/locking.rb
|
117
|
+
- lib/mongoid/locking/association/embedded/batchable.rb
|
117
118
|
- lib/mongoid/locking/contextual/atomic.rb
|
118
119
|
- lib/mongoid/locking/contextual/mongo.rb
|
119
120
|
- lib/mongoid/locking/persistable.rb
|
120
121
|
- lib/mongoid/locking/persistable/creatable.rb
|
121
122
|
- lib/mongoid/locking/persistable/updatable.rb
|
122
123
|
- lib/mongoid/locking/reloadable.rb
|
124
|
+
- lib/mongoid/locking/retry.rb
|
123
125
|
- lib/mongoid/locking/selectable.rb
|
124
126
|
- lib/mongoid/locking/version.rb
|
125
127
|
- lib/mongoid/stale_object_error.rb
|