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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d6150316b83b781d4f26eff62a82a593aff8f7a7a81791ae7b003801e9cc2f44
4
- data.tar.gz: 57a84b81757d94e4d4bfaceaea0f98f8437bd61bf7832be9e030fcb37fd5146c
3
+ metadata.gz: 59b03918904c46ce2770150d4b8d20d2b25ab735e6409982e804a9dbab8c4231
4
+ data.tar.gz: 316a1a9851bccd6580aedd95a9e5089a7b5a2ce4f9f2bc2b07a1af4f9ff4a263
5
5
  SHA512:
6
- metadata.gz: 743b07e99b92af64d0d209580f2a5851c44800a51c7c33e794cc655661abfeb86c65e1f8df66cd7eb42197466020cae038c85dd9dfd2656b7e187204cddcd3a1
7
- data.tar.gz: c14fb5d640c3bf4b6a4edfab3929aae1244a13f62ebe40641bd5a7a354357203f8f7e8add1e396ca07917d57cc3f4fd9af3ea3f3b5d589c3ceef17fa595de043
6
+ metadata.gz: dc860e6b8d43e812c6b7df124f72e1319041e795006f9dfd2c845cf0ee53d474c20d3d2c50b7d12e10e9b0b4f2eeb4180be38e6baa304b4bef132c14fcd89c9a
7
+ data.tar.gz: d545996296a982692f906ed2aa9ccd490855c153c6b949186552814250454168c0c8d8147efc8d5f094fb2f617a0ebc8c30ff02d8f93600143f227972a9fc83b
data/.rubocop.yml CHANGED
@@ -30,3 +30,6 @@ RSpec/DescribeClass:
30
30
 
31
31
  RSpec/MultipleExpectations:
32
32
  Enabled: false
33
+
34
+ RSpec/ExampleLength:
35
+ Max: 10
data/CHANGELOG.md CHANGED
@@ -1,4 +1,14 @@
1
- ## [Unreleased]
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.0.0)
5
- mongoid (~> 7.2.0)
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 (6.1.7.6)
11
- activesupport (= 6.1.7.6)
12
- activesupport (6.1.7.6)
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.2)
26
+ mongo (2.19.3)
28
27
  bson (>= 4.14.1, < 5.0.0)
29
- mongoid (7.2.6)
30
- activemodel (>= 5.1, < 6.2)
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.0)
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
- order.update(attributes)
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Mongoid
4
4
  module Locking
5
- VERSION = "1.1.0"
5
+ VERSION = "1.2.0"
6
6
  end
7
7
  end
@@ -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
- # base.include Mongoid::Locking::Reloadable if Mongoid::VERSION >= "7"
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.1.0
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-17 00:00:00.000000000 Z
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