mongoid-locker 2.1.0 → 2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e8773897b78e752adb20817abcc9ac800089614d3a1e3b797e2f551f87470d1
4
- data.tar.gz: e6283788f21ccefda79d62b61329530a6a996874ed067496c102f51087d6dd21
3
+ metadata.gz: 026c332edc7c13e914205576393e406b9b11fd472c8d854245f020ff78ec8ebf
4
+ data.tar.gz: 620e500a99272a299b9c2905dd5b387377a027e1c057c803c32fbac5546cd4ae
5
5
  SHA512:
6
- metadata.gz: 2922aac736bb767623cec9d51d69d80b51473d2e02be9265ddea767b29e4109185bc3ef259a8643697efc91cf7c1e7b506e7018ef46810e3881275ba18955138
7
- data.tar.gz: 5c215fb77dcba9646496f0eaf4735cdacd955540946d6cf5565d61c639764be3336e2123cdab050b1587444488e2ba82b4501955ad63aade3e289e353f9de75d
6
+ metadata.gz: c86887f8fce1b02266d55b3cbe36acf586d5fece20e51a585127a485325fa5360d14bf7ac2b9bcb32d91304d4dc4fcbf9176c2e2f31c989c3c92e60d5a8a39f9
7
+ data.tar.gz: d8ab164a30f027d642aa23324a3c67c59888d44549dc8b4c2be0baf89502818ce34c0027d22d0070cdaa895cec0fc1390af2861b3045b56bbc8c80adff44b702
@@ -1,17 +1,13 @@
1
1
  name: Danger
2
- on: [pull_request]
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, reopened, edited, synchronize]
6
+
3
7
  jobs:
4
8
  danger:
5
- runs-on: ubuntu-latest
6
- steps:
7
- - uses: actions/checkout@v3
8
- with:
9
- fetch-depth: 0
10
- - uses: ruby/setup-ruby@v1
11
- with:
12
- ruby-version: 2.7
13
- bundler-cache: true
14
- - run: |
15
- # Personal access token for dangerpr-bot - public, but base64 encoded to avoid tripping up GitHub
16
- TOKEN=$(echo -n Z2hwX0xNQ3VmanBFeTBvYkZVTWh6NVNqVFFBOEUxU25abzBqRUVuaAo= | base64 --decode)
17
- DANGER_GITHUB_API_TOKEN=$TOKEN bundle exec danger --verbose
9
+ uses: numbata/danger-pr-comment/.github/workflows/danger-run.yml@v0.1.0
10
+ secrets: inherit
11
+ with:
12
+ ruby-version: '3.4'
13
+ bundler-cache: true
@@ -4,10 +4,10 @@ jobs:
4
4
  lint:
5
5
  runs-on: ubuntu-latest
6
6
  steps:
7
- - uses: actions/checkout@v3
7
+ - uses: actions/checkout@v7
8
8
  - name: Set up Ruby
9
9
  uses: ruby/setup-ruby@v1
10
10
  with:
11
- ruby-version: 2.7
11
+ ruby-version: '3.4'
12
12
  bundler-cache: true
13
13
  - run: bundle exec rubocop
@@ -3,60 +3,80 @@ name: Test
3
3
  on: [push, pull_request]
4
4
 
5
5
  jobs:
6
+ sharding:
7
+ name: Sharded collections (MongoDB ${{ matrix.mongo }})
8
+ runs-on: ubuntu-22.04
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ mongo: ['6.0', '8.0']
13
+ env:
14
+ SHARDED_MONGODB_URI: mongodb://localhost:27028/mongoid_locker_sharding_test
15
+ steps:
16
+ - uses: actions/checkout@v7
17
+ - uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: '3.3'
20
+ bundler-cache: true
21
+ - name: Start sharded MongoDB
22
+ run: |
23
+ docker run -d --name locker-sharding -p 27028:27017 \
24
+ -v "$PWD/spec/integration/sharding/start.sh:/start.sh:ro" \
25
+ mongo:${{ matrix.mongo }} bash /start.sh
26
+ for attempt in $(seq 1 60); do
27
+ if docker exec locker-sharding mongosh --quiet --eval 'if (db.adminCommand({listShards:1}).shards.length !== 1) throw new Error("Shard not ready")' >/dev/null 2>&1; then
28
+ exit 0
29
+ fi
30
+ sleep 2
31
+ done
32
+ docker logs locker-sharding
33
+ exit 1
34
+ - name: Run sharding integration tests
35
+ run: bundle exec rspec spec/integration/sharding
6
36
  test:
7
-
8
37
  strategy:
9
38
  fail-fast: false
10
39
  matrix:
11
- entry:
12
- - { ruby: '2.6.6', mongo: 'mongo:4.4', mongoid: '5' }
13
- # - { ruby: 'jruby-9.1.17.0', mongo: 'mongo:4.4', mongoid: '5' }
14
- - { ruby: 'jruby-9.2.11.1', mongo: 'mongo:4.4', mongoid: '5' }
15
- - { ruby: '2.6.6', mongo: 'mongo:4.4', mongoid: '6' }
16
- - { ruby: '2.7.1', mongo: 'mongo:4.4', mongoid: '6' }
17
- - { ruby: '3.0.5', mongo: 'mongo:4.4', mongoid: '6' }
18
- - { ruby: '3.1.3', mongo: 'mongo:4.4', mongoid: '6' }
19
- - { ruby: 'jruby-9.2.11.1', mongo: 'mongo:4.4', mongoid: '6' }
20
- - { ruby: '2.6.6', mongo: 'mongo:4.4', mongoid: '7', coverage: 'true' }
21
- - { ruby: '2.7.1', mongo: 'mongo:4.4', mongoid: '7' }
22
- - { ruby: '3.0.5', mongo: 'mongo:4.4', mongoid: '7' }
23
- - { ruby: '3.1.3', mongo: 'mongo:4.4', mongoid: '7' }
24
- - { ruby: 'jruby-9.2.11.1', mongo: 'mongo:4.4', mongoid: '7' }
25
- - { ruby: '2.6.6', mongo: 'mongo:4.4', mongoid: '8' }
26
- - { ruby: '2.7.1', mongo: 'mongo:4.4', mongoid: '8' }
27
- - { ruby: '3.0.5', mongo: 'mongo:4.4', mongoid: '8' }
28
- - { ruby: '3.1.3', mongo: 'mongo:4.4', mongoid: '8' }
29
- - { ruby: '3.1.3', mongo: 'mongo:4.4', mongoid: '9' }
30
- experimental: [false]
31
-
32
- name: test (ruby=${{ matrix.entry.ruby }}, mongo=${{ matrix.entry.mongo }}, mongoid=${{ matrix.entry.mongoid }})
33
- runs-on: ubuntu-latest
34
-
35
- continue-on-error: ${{ matrix.experimental }}
36
-
40
+ include:
41
+ - { ruby: '2.6', mongo: '4.4', mongoid: '5' }
42
+ - { ruby: 'jruby-9.4', mongo: '4.4', mongoid: '5' }
43
+ - { ruby: '2.7', mongo: '4.4', mongoid: '6' }
44
+ - { ruby: '3.1', mongo: '4.4', mongoid: '6' }
45
+ - { ruby: 'jruby-9.4', mongo: '4.4', mongoid: '6' }
46
+ - { ruby: '3.0', mongo: '4.4', mongoid: '7' }
47
+ - { ruby: '3.4', mongo: '4.4', mongoid: '7' }
48
+ - { ruby: '2.6', mongo: '6.0', mongoid: '8' }
49
+ - { ruby: '3.1', mongo: '7.0', mongoid: '8' }
50
+ - { ruby: '3.3', mongo: '7.0', mongoid: '9' }
51
+ - { ruby: '3.4', mongo: '8.0', mongoid: '9' }
52
+ - { ruby: '4.0', mongo: '7.0', mongoid: '8' }
53
+ - { ruby: '4.0', mongo: '8.0', mongoid: '9', coverage: 'true' }
54
+ name: test (ruby=${{ matrix.ruby }}, mongo=${{ matrix.mongo }}, mongoid=${{ matrix.mongoid }})
55
+ runs-on: ubuntu-22.04
37
56
  services:
38
57
  mongo:
39
- image: ${{ matrix.entry.mongo }}
40
- ports: ["27017:27017"]
41
-
58
+ image: mongo:${{ matrix.mongo }}
59
+ ports: ['27017:27017']
60
+ options: >-
61
+ --health-cmd "mongosh --quiet --eval 'db.adminCommand({ping: 1})' || mongo --quiet --eval 'db.adminCommand({ping: 1})'"
62
+ --health-interval 10s
63
+ --health-timeout 5s
64
+ --health-retries 10
42
65
  env:
43
- MONGOID_VERSION: ${{ matrix.entry.mongoid }}
44
- COVERAGE: ${{ matrix.entry.coverage }}
45
-
66
+ MONGOID_VERSION: ${{ matrix.mongoid }}
67
+ COVERAGE: ${{ matrix.coverage }}
46
68
  steps:
47
- - uses: actions/checkout@v3
48
-
49
- - name: Set up Ruby
50
- uses: ruby/setup-ruby@v1
51
- with:
52
- ruby-version: ${{ matrix.entry.ruby }}
53
- bundler-cache: true
54
-
55
- - name: Run tests
56
- run: bundle exec rspec
57
-
58
- - name: Code Climate
59
- if: ${{ env.CC_TEST_REPORTER_ID != '' && success() && matrix.entry.coverage == 'true' }}
60
- uses: paambaati/codeclimate-action@v3.2.0
61
- env:
62
- CC_TEST_REPORTER_ID: ${{ vars.CC_TEST_REPORTER_ID }}
69
+ - uses: actions/checkout@v7
70
+ - uses: ruby/setup-ruby@v1
71
+ with:
72
+ ruby-version: ${{ matrix.ruby }}
73
+ bundler-cache: true
74
+ - name: Run tests
75
+ run: bundle exec rspec
76
+ - name: Report coverage
77
+ if: ${{ matrix.coverage == 'true' }}
78
+ uses: coverallsapp/github-action@v2
79
+ with:
80
+ github-token: ${{ secrets.GITHUB_TOKEN }}
81
+ file: coverage/.resultset.json
82
+ format: simplecov
data/.rspec CHANGED
@@ -1 +1,2 @@
1
1
  --require spec_helper
2
+ --format documentation
data/.rubocop.yml CHANGED
@@ -1,3 +1,7 @@
1
+ AllCops:
2
+ SuggestExtensions: true
3
+ NewCops: enable
4
+
1
5
  Lint/RaiseException:
2
6
  Enabled: true
3
7
 
@@ -21,4 +25,6 @@ RSpec/LeakyConstantDeclaration:
21
25
 
22
26
  inherit_from: .rubocop_todo.yml
23
27
 
24
- require: rubocop-rspec
28
+ plugins:
29
+ - rubocop-rspec
30
+ - rubocop-rake
data/.rubocop_todo.yml CHANGED
@@ -1,54 +1,71 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2020-04-07 15:05:45 -0400 using RuboCop version 0.81.0.
3
+ # on 2025-12-31 23:55:39 UTC using RuboCop version 1.81.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 3
10
- # Configuration parameters: Include.
11
- # Include: **/*.gemfile, **/Gemfile, **/gems.rb
12
- Bundler/DuplicatedGem:
9
+ # Offense count: 1
10
+ # Configuration parameters: Severity.
11
+ Gemspec/RequiredRubyVersion:
13
12
  Exclude:
14
- - 'Gemfile'
13
+ - 'mongoid-locker.gemspec'
15
14
 
16
- # Offense count: 4
17
- # Configuration parameters: IgnoredMethods.
18
- Metrics/AbcSize:
19
- Max: 24
15
+ # Offense count: 6
16
+ # Configuration parameters: AllowedMethods.
17
+ # AllowedMethods: enums
18
+ Lint/ConstantDefinitionInBlock:
19
+ Exclude:
20
+ - 'spec/support/configurations_shared_context.rb'
21
+ - 'spec/test_examples_spec.rb'
20
22
 
21
- # Offense count: 11
22
- # Configuration parameters: CountComments, ExcludedMethods.
23
- # ExcludedMethods: refine
24
- Metrics/BlockLength:
25
- Max: 290
23
+ # Offense count: 8
24
+ # Configuration parameters: AllowComments, AllowEmptyLambdas.
25
+ Lint/EmptyBlock:
26
+ Exclude:
27
+ - 'spec/support/locker_is_included_shared_examples.rb'
26
28
 
27
- # Offense count: 5
28
- # Configuration parameters: CountComments, ExcludedMethods.
29
+ # Offense count: 3
30
+ # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
31
+ Metrics/AbcSize:
32
+ Max: 27
33
+
34
+ # Offense count: 6
35
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
29
36
  Metrics/MethodLength:
30
37
  Max: 31
31
38
 
32
39
  # Offense count: 1
33
- # Configuration parameters: CountComments.
40
+ # Configuration parameters: CountComments, CountAsOne.
34
41
  Metrics/ModuleLength:
35
- Max: 105
42
+ Max: 109
36
43
 
37
44
  # Offense count: 2
38
- # Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
45
+ # Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, CheckDefinitionPathHierarchyRoots, Regex, IgnoreExecutableScripts, AllowedAcronyms.
46
+ # CheckDefinitionPathHierarchyRoots: lib, spec, test, src
39
47
  # AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
40
48
  Naming/FileName:
41
49
  Exclude:
50
+ - 'Rakefile.rb'
42
51
  - 'lib/mongoid-locker.rb'
43
52
  - 'spec/mongoid-locker_spec.rb'
44
53
 
45
54
  # Offense count: 1
46
- # Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros.
47
- # NamePrefix: is_, has_, have_
48
- # ForbiddenPrefixes: is_, has_, have_
55
+ # Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
56
+ # AllowedMethods: call
57
+ # WaywardPredicates: nonzero?
58
+ Naming/PredicateMethod:
59
+ Exclude:
60
+ - 'lib/mongoid/locker/wrapper.rb'
61
+
62
+ # Offense count: 1
63
+ # Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros, UseSorbetSigs.
64
+ # NamePrefix: is_, has_, have_, does_
65
+ # ForbiddenPrefixes: is_, has_, have_, does_
49
66
  # AllowedMethods: is_a?
50
67
  # MethodDefinitionMacros: define_method, define_singleton_method
51
- Naming/PredicateName:
68
+ Naming/PredicatePrefix:
52
69
  Exclude:
53
70
  - 'spec/**/*'
54
71
  - 'lib/mongoid/locker.rb'
@@ -56,28 +73,39 @@ Naming/PredicateName:
56
73
  # Offense count: 2
57
74
  RSpec/BeforeAfterAll:
58
75
  Exclude:
59
- - 'spec/spec_helper.rb'
60
- - 'spec/rails_helper.rb'
61
- - 'spec/support/**/*.rb'
76
+ - '**/spec/spec_helper.rb'
77
+ - '**/spec/rails_helper.rb'
78
+ - '**/spec/support/**/*.rb'
62
79
  - 'spec/test_examples_spec.rb'
63
80
 
64
81
  # Offense count: 1
82
+ # Configuration parameters: IgnoredMetadata.
65
83
  RSpec/DescribeClass:
66
84
  Exclude:
85
+ - '**/spec/features/**/*'
86
+ - '**/spec/requests/**/*'
87
+ - '**/spec/routing/**/*'
88
+ - '**/spec/system/**/*'
89
+ - '**/spec/views/**/*'
67
90
  - 'spec/test_examples_spec.rb'
68
91
 
69
- # Offense count: 8
70
- # Configuration parameters: Max.
92
+ # Offense count: 9
93
+ # Configuration parameters: CountAsOne.
71
94
  RSpec/ExampleLength:
95
+ Max: 11
96
+
97
+ # Offense count: 5
98
+ # This cop supports unsafe autocorrection (--autocorrect-all).
99
+ RSpec/IncludeExamples:
72
100
  Exclude:
101
+ - 'spec/mongoid-locker_spec.rb'
73
102
  - 'spec/support/locker_is_included_shared_examples.rb'
74
- - 'spec/test_examples_spec.rb'
103
+ - 'spec/support/locker_methods_shared_examples.rb'
75
104
 
76
- # Offense count: 1
77
- # Configuration parameters: CustomTransform, IgnoreMethods.
78
- RSpec/FilePath:
105
+ # Offense count: 2
106
+ RSpec/LetSetup:
79
107
  Exclude:
80
- - 'spec/mongoid-locker_spec.rb'
108
+ - 'spec/support/populate_database_shared_context.rb'
81
109
 
82
110
  # Offense count: 12
83
111
  # Configuration parameters: .
@@ -85,30 +113,70 @@ RSpec/FilePath:
85
113
  RSpec/MessageSpies:
86
114
  EnforcedStyle: receive
87
115
 
116
+ # Offense count: 12
117
+ # Configuration parameters: AllowSubject.
118
+ RSpec/MultipleMemoizedHelpers:
119
+ Max: 10
120
+
121
+ # Offense count: 2
122
+ # Configuration parameters: AllowedPatterns.
123
+ # AllowedPatterns: ^expect_, ^assert_
124
+ RSpec/NoExpectationExample:
125
+ Exclude:
126
+ - 'spec/support/locker_is_included_shared_examples.rb'
127
+
128
+ # Offense count: 1
129
+ RSpec/RemoveConst:
130
+ Exclude:
131
+ - 'spec/support/locker_helpers.rb'
132
+
133
+ # Offense count: 1
134
+ # Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
135
+ # SupportedInflectors: default, active_support
136
+ RSpec/SpecFilePathFormat:
137
+ Exclude:
138
+ - '**/spec/routing/**/*'
139
+ - 'spec/mongoid-locker_spec.rb'
140
+
88
141
  # Offense count: 1
89
142
  RSpec/SubjectStub:
90
143
  Exclude:
91
144
  - 'spec/support/delegated_methods_shared_examples.rb'
92
145
 
146
+ # Offense count: 1
147
+ # This cop supports unsafe autocorrection (--autocorrect-all).
148
+ Style/CollectionQuerying:
149
+ Exclude:
150
+ - 'lib/mongoid/locker.rb'
151
+
93
152
  # Offense count: 2
153
+ # Configuration parameters: AllowedConstants.
94
154
  Style/Documentation:
95
155
  Exclude:
96
156
  - 'spec/**/*'
97
157
  - 'test/**/*'
98
158
  - 'lib/mongoid/locker.rb'
99
159
 
160
+ # Offense count: 4
161
+ # This cop supports unsafe autocorrection (--autocorrect-all).
162
+ # Configuration parameters: AllowSplatArgument.
163
+ Style/HashConversion:
164
+ Exclude:
165
+ - 'spec/support/locker_is_included_shared_examples.rb'
166
+ - 'spec/support/locker_methods_shared_examples.rb'
167
+
100
168
  # Offense count: 2
101
- # Cop supports --auto-correct.
102
- # Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods.
169
+ # This cop supports unsafe autocorrection (--autocorrect-all).
170
+ # Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns.
103
171
  # SupportedStyles: predicate, comparison
104
172
  Style/NumericPredicate:
105
173
  Exclude:
106
174
  - 'spec/**/*'
107
175
  - 'lib/mongoid/locker.rb'
108
176
 
109
- # Offense count: 35
110
- # Cop supports --auto-correct.
111
- # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
177
+ # Offense count: 7
178
+ # This cop supports safe autocorrection (--autocorrect).
179
+ # Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
112
180
  # URISchemes: http, https
113
181
  Layout/LineLength:
114
182
  Max: 250
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  ## Changelog
2
2
 
3
+ ### 2.3.0 (2026-10-15)
4
+
5
+ * [#19](https://github.com/mongoid/mongoid-locker/issues/19): Add real sharded-cluster integration coverage for locking collections sharded by ranged and hashed `_id` - [@dblock](https://github.com/dblock).
6
+ * [#81](https://github.com/mongoid/mongoid-locker/issues/81): Document and test updating embedded documents under a parent lock, including stale references after the default reload - [@dblock](https://github.com/dblock).
7
+ * [#111](https://github.com/mongoid/mongoid-locker/pull/111): Replace the retired coverage integration with SimpleCov reporting to Coveralls and update CI and coverage badges - [@dblock](https://github.com/dblock).
8
+ * [#110](https://github.com/mongoid/mongoid-locker/pull/110): Modernize CI through Ruby 4.0, Mongoid 9 and MongoDB 8 while preserving legacy combinations and declaring missing test dependencies - [@dblock](https://github.com/dblock).
9
+ * [#109](https://github.com/mongoid/mongoid-locker/pull/109): Migrate Danger to use danger-pr-comment workflow - [@dblock](https://github.com/dblock).
10
+ * [#109](https://github.com/mongoid/mongoid-locker/pull/109): Remove support for Ruby 2.x - [@dblock](https://github.com/dblock).
11
+ * [#109](https://github.com/mongoid/mongoid-locker/pull/109): Add support for Ruby 4.0 - [@dblock](https://github.com/dblock).
12
+ ### 2.2.0 (2025-06-22)
13
+
14
+ * [#107](https://github.com/mongoid/mongoid-locker/pull/107): Revert introduction of `forwardable` to ensure compatibility with mongoid-history - [@scpike](https://github.com/scpike).
15
+
3
16
  ### 2.1.0 (2024-05-07)
4
17
 
5
18
  * [#101](https://github.com/mongoid/mongoid-locker/pull/101): Replace the $where operator with the $expr operator - [@amanfrinati](https://github.com/amanfrinati).
data/Dangerfile CHANGED
@@ -1,3 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- danger.import_dangerfile(gem: 'mongoid-danger')
3
+ danger.import_dangerfile(gem: 'danger-pr-comment')
4
+
5
+ changelog.check!
data/Gemfile CHANGED
@@ -3,9 +3,7 @@
3
3
  source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
- case ENV['MONGOID_VERSION']
7
- when /^9/
8
- gem 'mongoid', '~> 9.0'
6
+ case ENV.fetch('MONGOID_VERSION', nil)
9
7
  when /^8/
10
8
  gem 'mongoid', '~> 8.0'
11
9
  when /^7/
@@ -15,9 +13,13 @@ when /^6/
15
13
  when /^5/
16
14
  gem 'mongoid', '~> 5.4'
17
15
  else
18
- gem 'mongoid', '>= 5.0'
16
+ gem 'mongoid', '~> 9.0'
19
17
  end
20
18
 
19
+ gem 'base64'
20
+ gem 'benchmark'
21
+ gem 'mutex_m'
22
+ gem 'ostruct'
21
23
  gem 'rake'
22
24
 
23
25
  group :development do
@@ -25,12 +27,28 @@ group :development do
25
27
  end
26
28
 
27
29
  group :development, :test do
30
+ if ENV.fetch('MONGOID_VERSION', '').start_with?('5') && RUBY_ENGINE == 'ruby'
31
+ gem 'bigdecimal', '~> 1.3.5'
32
+ else
33
+ gem 'bigdecimal'
34
+ end
28
35
  gem 'pry-byebug', platforms: :mri
29
36
 
37
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7')
38
+ gem 'danger', require: false
39
+ gem 'danger-changelog', require: false
40
+ gem 'danger-pr-comment', require: false
41
+ end
30
42
  gem 'mongoid-compatibility'
31
- gem 'mongoid-danger', '~> 0.2.0'
43
+ gem 'mongoid-history'
32
44
  gem 'rspec', '~> 3.9'
33
- gem 'rubocop', '0.81.0'
34
- gem 'rubocop-rspec', '1.38.1'
45
+ gem 'rubocop', Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7') ? '0.81.0' : '1.81.1'
46
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7')
47
+ gem 'rubocop-rake', '< 0.7'
48
+ gem 'rubocop-rspec', '1.38.1'
49
+ else
50
+ gem 'rubocop-rake', '>= 0.7'
51
+ gem 'rubocop-rspec', '>= 3.7'
52
+ end
35
53
  gem 'simplecov', require: false
36
54
  end
data/README.md CHANGED
@@ -1,9 +1,8 @@
1
1
  # Mongoid-Locker
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/mongoid-locker.svg)](https://badge.fury.io/rb/mongoid-locker)
4
- [![Test](https://github.com/mongoid/mongoid-locker/actions/workflows/test.yml/badge.svg)](https://github.com/mongoid/mongoid-locker/actions/workflows/test.yml)
5
- [![Maintainability](https://api.codeclimate.com/v1/badges/04ee4ee75ff54659300a/maintainability)](https://codeclimate.com/github/mongoid/mongoid-locker/maintainability)
6
- [![Test Coverage](https://api.codeclimate.com/v1/badges/04ee4ee75ff54659300a/test_coverage)](https://codeclimate.com/github/mongoid/mongoid-locker/test_coverage)
4
+ [![CI](https://github.com/mongoid/mongoid-locker/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/mongoid/mongoid-locker/actions/workflows/test.yml?query=branch%3Amaster)
5
+ [![Coverage Status](https://coveralls.io/repos/github/mongoid/mongoid-locker/badge.svg?branch=master)](https://coveralls.io/github/mongoid/mongoid-locker?branch=master)
7
6
 
8
7
  Document-level optimistic locking for MongoDB via Mongoid. Mongoid-Locker is an easy way to ensure only one process can perform a certain operation on a document at a time.
9
8
 
@@ -12,7 +11,7 @@ Document-level optimistic locking for MongoDB via Mongoid. Mongoid-Locker is an
12
11
  **NOTE:** Please refer to [1-x-stable](https://github.com/mongoid/mongoid-locker/tree/1-x-stable) branch for `1.x.x` documentation. See the [UPGRADING](UPGRADING.md) guide and [CHANGELOG](CHANGELOG.md) for an overview of the changes.
13
12
 
14
13
  [Tested](https://github.com/mongoid/mongoid-locker/actions) against:
15
- - MRI: `2.3.8`, `2.4.7`, `2.5.7`, `2.6.6`, `2.7.1`, `3.0.5`, `3.1.3`
14
+ - MRI: `3.x`, `4.x`
16
15
  - JRuby `9.1.17.0`, `9.2.11.1`
17
16
  - Mongoid: `5`, `6`, `7`, `8`, `9`
18
17
 
@@ -55,6 +54,23 @@ Note that these locks are only enforced when using `#with_lock`, not at the data
55
54
 
56
55
  More in-depth method documentation can be found at [RubyDoc.info](https://www.rubydoc.info/gems/mongoid-locker).
57
56
 
57
+ ### Updating Embedded Documents
58
+
59
+ Lock the root document and retrieve embedded documents **inside** the `with_lock` block. By default, acquiring a lock reloads the root document before yielding, replacing its cached embedded documents. An embedded document reference obtained before locking is therefore stale: changing it and saving the reloaded parent does not persist that child's changes. Unsaved changes made before acquiring the lock can also be discarded by the reload.
60
+
61
+ ```ruby
62
+ parent.with_lock do
63
+ child = parent.children.first
64
+ child.status = 2
65
+ parent.option = 4
66
+ parent.save!
67
+ end
68
+ ```
69
+
70
+ If you select a particular child before locking, keep its ID and retrieve it again inside the block with `parent.children.find(child_id)`. This preserves the default reload, so the update works with the current persisted state.
71
+
72
+ Alternatively, `parent.with_lock(reload: false)` preserves existing in-memory embedded references, but does not refresh the parent or its children after acquiring the lock. Use it only when you deliberately want to work with the state already loaded; acquiring the lock does not make that state current.
73
+
58
74
  ### Customizable :locking_name and :locked_at field names
59
75
  By default, Locker uses fields with `:locking_name` and `:locked_at` names which should be defined in a model.
60
76
  ```ruby
@@ -156,6 +172,25 @@ class User
156
172
  ## Testing with RSpec
157
173
  Please see examples in [test_examples_spec.rb](spec/test_examples_spec.rb) file.
158
174
 
175
+ ### Sharded Collections
176
+
177
+ Locking is integration-tested through a real `mongos` router with collections sharded by ranged and hashed `_id` keys. These tests cover acquiring and releasing locks, contention, expired locks, and exceptions. They use a single-shard cluster; they do not test chunk migrations or arbitrary non-`_id` shard keys.
178
+
179
+ To run the sharding tests locally, start the disposable cluster and wait until its shard is registered:
180
+
181
+ ```sh
182
+ docker run -d --name locker-sharding -p 127.0.0.1:27028:27017 \
183
+ -v "$PWD/spec/integration/sharding/start.sh:/start.sh:ro" \
184
+ mongo:8.0 bash /start.sh
185
+ docker exec locker-sharding mongosh --quiet --eval 'db.adminCommand({listShards:1})'
186
+ SHARDED_MONGODB_URI=mongodb://localhost:27028/mongoid_locker_sharding_test \
187
+ bundle exec rspec spec/integration/sharding
188
+ docker stop locker-sharding
189
+ docker rm locker-sharding
190
+ ```
191
+
192
+ Use a dedicated test database: these tests drop and recreate their collection. Without `SHARDED_MONGODB_URI`, they are skipped by the normal suite. CI starts the cluster and runs them separately on MongoDB 6.0 and 8.0.
193
+
159
194
  ## Copyright & License
160
195
 
161
196
  Copyright (c) 2012-2020 Aidan Feldman & Contributors
data/RELEASING.md CHANGED
@@ -1,67 +1,51 @@
1
- Releasing Mongoid::Locker
2
- =========================
1
+ # Releasing Mongoid::Locker
3
2
 
4
- There're no particular rules about when to release mongoid-locker. Release bug fixes frequently, features not so frequently and breaking API changes rarely.
3
+ ## Prepare
5
4
 
6
- ### Release
5
+ Use the upstream checkout on a clean `master`, verify `origin` points to `mongoid/mongoid-locker`, and run `git pull --ff-only`. Review existing CI results for supported platforms. Use patch versions for fixes, minor versions for backward-compatible features, and major versions for breaking changes.
7
6
 
8
- Run tests, check that all tests succeed locally.
7
+ Set the version in `lib/mongoid/locker/version.rb`, date its section in `CHANGELOG.md` using `YYYY-MM-DD`, and remove that section's contribution placeholder.
9
8
 
10
- ```
9
+ ```sh
11
10
  bundle install
12
- bundle exec rake
13
- ```
14
-
15
- Check that the last build succeeded in [GitHub Actions](https://github.com/mongoid/mongoid-locker/actions) for all supported platforms.
16
-
17
- Check the version, if needed modify [lib/mongoid/locker/version.rb](lib/mongoid/locker/version.rb).
18
-
19
- * Increment the third number if the release has bug fixes and/or very minor features, only (eg. change `0.5.1` to `0.5.2`).
20
- * Increment the second number if the release contains major features or breaking API changes (eg. change `0.5.1` to `0.4.0`).
21
-
22
- Change "Next Release" in [CHANGELOG.md](CHANGELOG.md) to the new version.
23
-
24
- ```
25
- ### 0.4.0 (2014-01-27)
26
- ```
27
-
28
- Remove the line with "Your contribution here.", since there will be no more contributions to this release.
29
-
30
- Commit your changes.
31
-
32
- ```
33
- git add CHANGELOG.md lib/mongoid-locker/version.rb
34
- git commit -m "Preparing for release, 0.4.0."
11
+ bundle exec rspec
12
+ bundle exec rubocop
13
+ git add CHANGELOG.md lib/mongoid/locker/version.rb RELEASING.md
14
+ git commit -m "Preparing for release, 2.3.0."
35
15
  git push origin master
36
16
  ```
37
17
 
38
- Release.
18
+ Do not wait for the preparation commit's CI checks before publishing.
39
19
 
40
- ```
41
- $ bundle exec rake release
20
+ ## Publish RubyGems and GitHub
42
21
 
43
- mongoid-locker 0.4.0 built to pkg/mongoid-locker-0.4.0.gem.
44
- Tagged v0.4.0.
45
- Pushed git commits and tags.
46
- Pushed mongoid-locker 0.4.0 to rubygems.org.
22
+ ```sh
23
+ bundle exec rake release
47
24
  ```
48
25
 
49
- ### Prepare for the Next Version
50
-
51
- Increment the minor version, modify [lib/mongoid-locker/version.rb](lib/mongoid-locker/version.rb).
26
+ Complete RubyGems MFA when requested. This builds the gem, pushes the release tag, and publishes to RubyGems. If interrupted, inspect the existing tag and published version before retrying. Never move a published tag. If only publication is missing, run `gem push pkg/mongoid-locker-2.3.0.gem` with a fresh MFA code.
52
27
 
53
- Add the next release to [CHANGELOG.md](CHANGELOG.md).
28
+ A tag is not a GitHub release. After verifying RubyGems publication, create a matching release with the changelog notes:
54
29
 
30
+ ```sh
31
+ version=2.3.0
32
+ notes="$(mktemp)"
33
+ awk -v version="$version" '
34
+ /^### / {
35
+ if (found) exit
36
+ if ($2 == version) found = 1
37
+ next
38
+ }
39
+ found { print }
40
+ ' CHANGELOG.md > "$notes"
41
+ gh release create "v$version" --repo mongoid/mongoid-locker --verify-tag --title "$version" --notes-file "$notes" --latest
42
+ rm "$notes"
43
+ curl --fail --silent --show-error "https://rubygems.org/api/v2/rubygems/mongoid-locker/versions/$version.json"
44
+ gh release view "v$version" --repo mongoid/mongoid-locker
55
45
  ```
56
- ### 0.4.1 (Next)
57
46
 
58
- * Your contribution here.
59
- ```
47
+ Verify both the published gem and non-draft GitHub release.
60
48
 
61
- Commit your changes.
49
+ ## Prepare the Next Version
62
50
 
63
- ```
64
- git add CHANGELOG.md lib/mongoid-locker/version.rb
65
- git commit -m "Preparing for next release, 0.4.1."
66
- git push origin master
67
- ```
51
+ Increment the development patch version in `lib/mongoid/locker/version.rb`, for example to `2.3.1`. Add `### 2.3.1 (Next)` and a contribution placeholder above the released changelog section. Commit and push these changes to `master`, leaving the release tag unchanged.
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Mongoid
4
4
  module Locker
5
- VERSION = '2.1.0'
5
+ VERSION = '2.3.0'
6
6
  end
7
7
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
4
3
  require 'securerandom'
5
4
 
6
5
  module Mongoid
@@ -46,7 +45,7 @@ module Mongoid
46
45
  # @param opts [Hash] (see #with_lock)
47
46
  # @return [Float]
48
47
  def exponential_backoff(_doc, opts)
49
- 2**opts[:attempt] + rand
48
+ (2**opts[:attempt]) + rand
50
49
  end
51
50
 
52
51
  # Returns time in seconds remaining to complete the lock of the provided document. Makes requests to the database.
@@ -104,8 +103,6 @@ module Mongoid
104
103
 
105
104
  # @api private
106
105
  def included(klass)
107
- klass.extend(Forwardable) unless klass.ancestors.include?(Forwardable)
108
-
109
106
  klass.extend ClassMethods
110
107
  klass.singleton_class.instance_eval { attr_accessor(*MODULE_METHODS) }
111
108
 
@@ -117,8 +114,10 @@ module Mongoid
117
114
  klass.backoff_algorithm = backoff_algorithm
118
115
  klass.locking_name_generator = locking_name_generator
119
116
 
120
- klass.def_delegators(klass, *MODULE_METHODS)
121
- klass.singleton_class.delegate(*(methods(false) - MODULE_METHODS.flat_map { |method| [method, "#{method}=".to_sym] } - %i[included reset! configure]), to: self)
117
+ klass.delegate(*MODULE_METHODS, to: :class)
118
+ klass.singleton_class.delegate(*(methods(false) - MODULE_METHODS.flat_map do |method|
119
+ [method, :"#{method}="]
120
+ end - %i[included reset! configure]), to: self)
122
121
  end
123
122
  end
124
123
 
@@ -205,7 +204,10 @@ module Mongoid
205
204
  # @param locking_name_generator [Symbol]
206
205
  def locker(**params)
207
206
  invalid_parameters = params.keys - Mongoid::Locker.singleton_class.const_get('MODULE_METHODS')
208
- raise Mongoid::Locker::Errors::InvalidParameter.new(self.class, invalid_parameters.first) unless invalid_parameters.empty?
207
+ unless invalid_parameters.empty?
208
+ raise Mongoid::Locker::Errors::InvalidParameter.new(self.class,
209
+ invalid_parameters.first)
210
+ end
209
211
 
210
212
  params.each_pair do |key, value|
211
213
  send("#{key}=", value)
@@ -274,7 +276,10 @@ module Mongoid
274
276
  opts[:attempt] += 1
275
277
  delay = self.class.send(backoff_algorithm, self, opts)
276
278
 
277
- raise Errors::DocumentCouldNotGetLock.new(self.class, id) if delay >= maximum_backoff || opts[:attempt] >= opts[:retries]
279
+ if delay >= maximum_backoff || opts[:attempt] >= opts[:retries]
280
+ raise Errors::DocumentCouldNotGetLock.new(self.class,
281
+ id)
282
+ end
278
283
 
279
284
  sleep delay
280
285
  end
@@ -19,4 +19,5 @@ Gem::Specification.new do |s|
19
19
  s.require_paths = ['lib']
20
20
 
21
21
  s.add_dependency 'mongoid', '>= 5.0', '< 10'
22
+ s.metadata['rubygems_mfa_required'] = 'true'
22
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-locker
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aidan Feldman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-07 00:00:00.000000000 Z
11
+ date: 2026-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mongoid
@@ -65,7 +65,8 @@ files:
65
65
  homepage: https://github.com/mongoid/mongoid-locker
66
66
  licenses:
67
67
  - MIT
68
- metadata: {}
68
+ metadata:
69
+ rubygems_mfa_required: 'true'
69
70
  post_install_message:
70
71
  rdoc_options: []
71
72
  require_paths:
@@ -81,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
81
82
  - !ruby/object:Gem::Version
82
83
  version: '0'
83
84
  requirements: []
84
- rubygems_version: 3.3.7
85
+ rubygems_version: 3.5.16
85
86
  signing_key:
86
87
  specification_version: 4
87
88
  summary: Document-level optimistic locking for MongoDB via Mongoid.