mongoid-locker 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1bd397a8299e68e225e9df96570840b39592559e458f808834722548fb486387
4
- data.tar.gz: a6d879248d41b1f6e1b0eeb715dc4ba72c93042c7e382d56743f53c40868007e
3
+ metadata.gz: 83a2fc5d9474fb911afd4cb106587e84aa7209ee8875b578feaabdff226c3be1
4
+ data.tar.gz: 8bdfc514dd4649646ea3de44ebf0892b6b9b74a83aadffd5d2c5694177842ba6
5
5
  SHA512:
6
- metadata.gz: 29b6005758187e0020a375971f37da4c0d476cdec634f2dda35b0e78695b26da00c4ff6e8f2dab98c4f9b628514668be8135336d87f525cd974cf55c7c9cd8db
7
- data.tar.gz: 1df8d96ae35dee15bf9ce2225cc3834ef0b055e95c68b4685e5f3efbeddab5a1af87fb129a800d558c9d2692fce59ce1fa72b9ca968a3519d9614a884f30cfc5
6
+ metadata.gz: fdd9b3d0ad671dd6b2bbf862f47cb7b642446d2f8642861de0d755ee7143e61eb60e3a3f6614f235ed79c09085ff408c4f1a4f39707379c358e655748229866c
7
+ data.tar.gz: 2cb5ec0046da6f2d6f7b58e8bac93ea6297da9ae3279281b68b0528ebe527b0e6b928db29a280e3282e19c34d16b1e289e6947ab45f1bf33c70bf6864ccc4c9d
data/.gitignore CHANGED
@@ -1,19 +1,14 @@
1
1
  # simplecov
2
2
  coverage
3
3
 
4
- # rdoc
5
- rdoc
6
-
7
4
  # yard
8
5
  doc
9
6
  .yardoc
10
7
 
11
8
  # bundler
12
- .bundle
13
9
  pkg
10
+ .bundle
11
+ Gemfile.lock
14
12
 
15
13
  # guard
16
14
  tmp
17
-
18
- # bundler
19
- Gemfile.lock
data/.rspec CHANGED
@@ -1,2 +1 @@
1
- --color
2
- --format documentation
1
+ --require spec_helper
@@ -1,32 +1,37 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2018-11-23 00:20:08 +0300 using RuboCop version 0.60.0.
3
+ # on 2019-10-23 10:17:29 -0400 using RuboCop version 0.75.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: 4
9
+ # Offense count: 3
10
10
  # Configuration parameters: Include.
11
11
  # Include: **/*.gemfile, **/Gemfile, **/gems.rb
12
12
  Bundler/DuplicatedGem:
13
13
  Exclude:
14
14
  - 'Gemfile'
15
15
 
16
- # Offense count: 2
16
+ # Offense count: 4
17
17
  Metrics/AbcSize:
18
- Max: 20
18
+ Max: 21
19
19
 
20
- # Offense count: 5
20
+ # Offense count: 10
21
21
  # Configuration parameters: CountComments, ExcludedMethods.
22
22
  # ExcludedMethods: refine
23
23
  Metrics/BlockLength:
24
- Max: 505
24
+ Max: 292
25
25
 
26
- # Offense count: 3
26
+ # Offense count: 5
27
27
  # Configuration parameters: CountComments, ExcludedMethods.
28
28
  Metrics/MethodLength:
29
- Max: 25
29
+ Max: 31
30
+
31
+ # Offense count: 1
32
+ # Configuration parameters: CountComments.
33
+ Metrics/ModuleLength:
34
+ Max: 104
30
35
 
31
36
  # Offense count: 2
32
37
  # Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
@@ -47,19 +52,20 @@ Naming/PredicateName:
47
52
  - 'spec/**/*'
48
53
  - 'lib/mongoid/locker.rb'
49
54
 
50
- # Offense count: 37
51
- # Cop supports --auto-correct.
52
- # Configuration parameters: SkipBlocks, EnforcedStyle.
53
- # SupportedStyles: described_class, explicit
54
- RSpec/DescribedClass:
55
+ # Offense count: 12
56
+ # Configuration parameters: Prefixes.
57
+ # Prefixes: when, with, without
58
+ RSpec/ContextWording:
55
59
  Exclude:
56
- - 'spec/mongoid-locker_spec.rb'
60
+ - 'spec/support/configurations_shared_context.rb'
61
+ - 'spec/support/populate_database_shared_context.rb'
62
+ - 'spec/support/reset_shared_context.rb'
57
63
 
58
- # Offense count: 19
64
+ # Offense count: 7
59
65
  # Configuration parameters: Max.
60
66
  RSpec/ExampleLength:
61
67
  Exclude:
62
- - 'spec/mongoid-locker_spec.rb'
68
+ - 'spec/support/locker_is_included_shared_examples.rb'
63
69
 
64
70
  # Offense count: 1
65
71
  # Configuration parameters: CustomTransform, IgnoreMethods.
@@ -67,16 +73,21 @@ RSpec/FilePath:
67
73
  Exclude:
68
74
  - 'spec/mongoid-locker_spec.rb'
69
75
 
70
- # Offense count: 6
76
+ # Offense count: 5
77
+ RSpec/LeakyConstantDeclaration:
78
+ Exclude:
79
+ - 'spec/support/configurations_shared_context.rb'
80
+
81
+ # Offense count: 12
71
82
  # Configuration parameters: .
72
83
  # SupportedStyles: have_received, receive
73
84
  RSpec/MessageSpies:
74
85
  EnforcedStyle: receive
75
86
 
76
- # Offense count: 16
87
+ # Offense count: 11
77
88
  # Configuration parameters: AggregateFailuresByDefault.
78
89
  RSpec/MultipleExpectations:
79
- Max: 5
90
+ Max: 3
80
91
 
81
92
  # Offense count: 2
82
93
  Style/Documentation:
@@ -86,12 +97,17 @@ Style/Documentation:
86
97
  - 'lib/mongoid/locker.rb'
87
98
 
88
99
  # Offense count: 2
89
- Style/DoubleNegation:
100
+ # Cop supports --auto-correct.
101
+ # Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods.
102
+ # SupportedStyles: predicate, comparison
103
+ Style/NumericPredicate:
90
104
  Exclude:
105
+ - 'spec/**/*'
91
106
  - 'lib/mongoid/locker.rb'
92
107
 
93
- # Offense count: 55
94
- # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
108
+ # Offense count: 33
109
+ # Cop supports --auto-correct.
110
+ # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
95
111
  # URISchemes: http, https
96
112
  Metrics/LineLength:
97
- Max: 180
113
+ Max: 250
@@ -5,49 +5,37 @@ language: ruby
5
5
 
6
6
  cache: bundler
7
7
 
8
- before_install:
9
- - gem update --system
10
- - gem install bundler
8
+ script:
9
+ - bundle exec rspec
10
+
11
+ rvm:
12
+ - 2.3.8
13
+ - 2.4.5
14
+ - 2.5.4
15
+ - 2.6.2
16
+ - jruby-9.1.17.0
17
+ - jruby-9.2.6.0
18
+
19
+ env:
20
+ - MONGOID_VERSION=5
21
+ - MONGOID_VERSION=6
22
+ - MONGOID_VERSION=7
11
23
 
12
24
  matrix:
13
25
  include:
14
- - rvm: 2.3.8
15
- env: MONGOID_VERSION=4
16
- - rvm: 2.3.8
17
- env: MONGOID_VERSION=5
18
- - rvm: 2.3.8
19
- env: MONGOID_VERSION=6
20
- - rvm: 2.4.5
21
- env: MONGOID_VERSION=6
22
- - rvm: 2.4.5
23
- env: MONGOID_VERSION=7
24
- - rvm: 2.5.3
25
- env: MONGOID_VERSION=7
26
- before_script: bundle exec danger
27
- - rvm: jruby-9.1.17.0
28
- env: MONGOID_VERSION=4
29
- - rvm: jruby-9.1.17.0
30
- env: MONGOID_VERSION=5
31
- - rvm: jruby-9.1.17.0
32
- env: MONGOID_VERSION=6
33
- - rvm: jruby-9.2.4.0
34
- env: MONGOID_VERSION=6
35
- - rvm: jruby-9.2.4.0
36
- env: MONGOID_VERSION=7
37
- - name: Code Climate Test Coverage
38
- rvm: 2.3.8
39
- env: COVERAGE=true
40
- script:
41
- - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
42
- - chmod +x ./cc-test-reporter
43
- - ./cc-test-reporter before-build
44
- - for version in 4 5 6 7; do
45
- MONGOID_VERSION=$version bundle update;
46
- bundle exec rake;
47
- ./cc-test-reporter format-coverage -t simplecov -o coverage/codeclimate.mongoid${version}.json;
48
- done
26
+ - rvm: 2.6.2
27
+ env:
28
+ - MONGOID_VERSION=7
29
+ - COVERAGE=true
30
+ before_script:
31
+ - bundle exec rubocop
32
+ - bundle exec danger
33
+ after_script:
49
34
  - if [[ "$TRAVIS_TEST_RESULT" == 0 ]]; then
50
- ./cc-test-reporter sum-coverage coverage/codeclimate.mongoid*.json -p 4;
35
+ curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter;
36
+ chmod +x ./cc-test-reporter;
37
+ ./cc-test-reporter before-build;
38
+ ./cc-test-reporter format-coverage -t simplecov -o coverage/codeclimate.json coverage/.resultset.json;
51
39
  ./cc-test-reporter upload-coverage;
52
40
  fi
53
41
  - rvm: ruby-head
@@ -55,8 +43,6 @@ matrix:
55
43
  fast_finish: true
56
44
  allow_failures:
57
45
  - rvm: ruby-head
58
- - rvm: jruby-9.1.17.0
59
- - rvm: jruby-9.2.4.0
60
46
  - rvm: jruby-head
61
47
 
62
48
  bundler_args: --without development
@@ -1,5 +1,11 @@
1
1
  ## Changelog
2
2
 
3
+ ### 2.0.0 (2019-10-23)
4
+
5
+ * [#79](https://github.com/mongoid/mongoid-locker/pull/79): Update find_and_lock and find_and_unlock methods - [@dks17](https://github.com/dks17).
6
+ * [#78](https://github.com/mongoid/mongoid-locker/pull/78): Upgrade to v2.0 - [@dks17](https://github.com/dks17).
7
+ * [#83](https://github.com/mongoid/mongoid-locker/pull/83): Upgraded to RuboCop 0.75.1 - [@dblock](https://github.com/dblock).
8
+
3
9
  ### 1.0.1 (2019-03-23)
4
10
 
5
11
  * [#74](https://github.com/mongoid/mongoid-locker/pull/74): Add JRuby tests - [@dks17](https://github.com/dks17).
data/Dangerfile CHANGED
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  danger.import_dangerfile(gem: 'mongoid-danger')
data/Gemfile CHANGED
@@ -1,4 +1,7 @@
1
- source 'http://rubygems.org'
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+ gemspec
2
5
 
3
6
  case ENV['MONGOID_VERSION']
4
7
  when /^7/
@@ -7,25 +10,22 @@ when /^6/
7
10
  gem 'mongoid', '~> 6.4'
8
11
  when /^5/
9
12
  gem 'mongoid', '~> 5.4'
10
- when /^4/
11
- gem 'mongoid', '~> 4.0'
12
13
  else
13
- gem 'mongoid', '>= 4.0'
14
+ gem 'mongoid', '>= 5.0'
14
15
  end
15
16
 
16
- gemspec
17
+ gem 'rake'
17
18
 
18
19
  group :development do
19
20
  gem 'guard-rspec'
20
- gem 'rb-fsevent', '~> 0.9.1'
21
21
  end
22
22
 
23
23
  group :development, :test do
24
+ gem 'pry-byebug', platforms: :mri
25
+
24
26
  gem 'mongoid-danger', '~> 0.1.1'
25
- gem 'rack', '~> 1.5'
26
- gem 'rake', '11.3.0'
27
- gem 'rspec', '~> 3.0'
28
- gem 'rubocop'
27
+ gem 'rspec', '~> 3.8'
28
+ gem 'rubocop', '0.75.1'
29
29
  gem 'rubocop-rspec'
30
30
  gem 'simplecov', require: false
31
31
  end
data/Guardfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # More info at https://github.com/guard/guard#readme
2
4
 
3
5
  guard :rspec, cmd: 'bundle exec rspec', all_on_start: true do
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-2018 Aidan Feldman & Contributors
1
+ Copyright (c) 2012-2019 Aidan Feldman & Contributors
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,14 +1,20 @@
1
- # mongoid-locker
1
+ # Mongoid-Locker
2
+
2
3
  [![Gem Version](https://badge.fury.io/rb/mongoid-locker.svg)](https://badge.fury.io/rb/mongoid-locker)
3
4
  [![Build Status](https://travis-ci.org/mongoid/mongoid-locker.svg?branch=master)](https://travis-ci.org/mongoid/mongoid-locker)
4
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/04ee4ee75ff54659300a/maintainability)](https://codeclimate.com/github/mongoid/mongoid-locker/maintainability)
5
6
  [![Test Coverage](https://api.codeclimate.com/v1/badges/04ee4ee75ff54659300a/test_coverage)](https://codeclimate.com/github/mongoid/mongoid-locker/test_coverage)
6
7
 
7
- Document-level 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.
8
+ 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
+
10
+ **NOTE:** Since version `2` Mongoid-Locker relies on MongoDB server time and not current client time, and does not perform any time calculation to get lock or release it. The basis of the current version are unique name of locking and time is set by MongoDB.
11
+
12
+ **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.
8
13
 
9
14
  [Tested](https://travis-ci.org/mongoid/mongoid-locker) against:
10
- - MRI: `2.3.8`, `2.4.5`, `2.5.3`
11
- - Mongoid: `4`, `5`, `6`, `7`
15
+ - MRI: `2.3.8`, `2.4.5`, `2.5.4`, `2.6.2`
16
+ - JRuby `9.1.17.0`, `9.2.6.0`
17
+ - Mongoid: `5`, `6`, `7`
12
18
 
13
19
  See [.travis.yml](.travis.yml) for the latest test matrix.
14
20
 
@@ -23,88 +29,134 @@ gem 'mongoid-locker'
23
29
  and run `bundle install`. In the model you wish to lock, include `Mongoid::Locker` after `Mongoid::Document`. For example:
24
30
 
25
31
  ```ruby
26
- class QueueItem
32
+ class User
27
33
  include Mongoid::Document
28
34
  include Mongoid::Locker
29
35
 
36
+ field :locking_name, type: String
30
37
  field :locked_at, type: Time
31
- field :locked_until, type: Time
32
38
 
33
- field :completed_at, type: Time
39
+ field :age, type: Integer
40
+
41
+ index({ _id: 1, locking_name: 1 }, name: 'mongoid_locker_index', sparse: true, unique: true, expire_after_seconds: lock_timeout)
34
42
  end
35
43
  ```
36
44
 
37
45
  Then, execute any code you like in a block like so:
38
46
 
39
47
  ```ruby
40
- queue_item.with_lock do
41
-
42
- # do stuff
43
-
44
- queue_item.completed_at = Time.now.utc
45
- queue_item.save!
48
+ user.with_lock do
49
+ user.age = 17
50
+ user.save!
46
51
  end
47
52
  ```
48
53
 
49
- The `#with_lock` function takes an optional [handful of options around retrying](http://rdoc.info/github/mongoid/mongoid-locker/Mongoid/Locker:with_lock), so make sure to take a look.
50
-
51
- The default timeout can also be set on a per-class basis:
52
-
53
- ```ruby
54
- class QueueItem
55
- # ...
56
- timeout_lock_after 10
57
- end
58
- ```
54
+ The `#with_lock` function takes an optional handful of options, so make sure to take a look.
59
55
 
60
56
  Note that these locks are only enforced when using `#with_lock`, not at the database level. It's useful for transactional operations, where you can make atomic modification of the document with checks. For example, you could deduct a purchase from a user's balance ... _unless_ they are broke.
61
57
 
62
- More in-depth method documentation can be found at [rdoc.info](http://rdoc.info/github/mongoid/mongoid-locker/frames).
58
+ More in-depth method documentation can be found at [RubyDoc.info](https://www.rubydoc.info/gems/mongoid-locker).
63
59
 
64
- ### Customizable :locked_at and :locked_until field names
65
- By default, Locker uses fields with `:locked_at` and `:locked_until` names which should be defined in a model.
60
+ ### Customizable :locking_name and :locked_at field names
61
+ By default, Locker uses fields with `:locking_name` and `:locked_at` names which should be defined in a model.
66
62
  ```ruby
67
63
  class User
68
64
  include Mongoid::Document
69
65
  include Mongoid::Locker
70
66
 
67
+ field :locking_name, type: String
71
68
  field :locked_at, type: Time
72
- field :locked_until, type: Time
73
69
  end
74
70
  ```
75
71
 
76
- Use `Mongoid::Locker.configure` to setup field names which used by Locker for all models where it's included.
72
+ Use `Mongoid::Locker.configure` to setup parameters which used by Locker for all models where it's included.
77
73
  ```ruby
78
74
  Mongoid::Locker.configure do |config|
79
- config.locked_at_field = :global_locked_at
80
- config.locked_until_field = :global_locked_until
75
+ config.locking_name_field = :global_locking_name
76
+ config.locked_at_field = :global_locked_at
81
77
  end
82
78
 
83
79
  class User
84
80
  include Mongoid::Document
85
81
  include Mongoid::Locker
86
82
 
83
+ field :global_locking_name, type: String
87
84
  field :global_locked_at, type: Time
88
- field :global_locked_until, type: Time
89
85
  end
90
86
  ```
91
87
 
92
- The `locker` method in your model accepts `:locked_at_field` and `:locked_until_field` options to setup field names which used by Locker for the model. This can be useful when another library uses the same field for different purposes.
88
+ The `locker` method in your model accepts options to setup parameters for the model.
93
89
  ```ruby
94
90
  class User
95
91
  include Mongoid::Document
96
92
  include Mongoid::Locker
97
93
 
94
+ field :locker_locking_name, type: String
98
95
  field :locker_locked_at, type: Time
99
- field :locker_locked_until, type: Time
100
96
 
101
- locker locked_at_field: :locker_locked_at,
102
- locked_until_field: :locker_locked_until
97
+ locker locked_at_field: :locker_locking_name,
98
+ locked_at_field: :locker_locked_at
99
+ end
100
+ ```
101
+
102
+ ### Available parameters for Mongoid::Locker, a class where it's included
103
+ | parameter | default | options | description |
104
+ |---|---|---|---|
105
+ | locking_name_field | `:locking_name` | any field name | field where name of locking is storing, must be of type `String` |
106
+ | locked_at_field | `:locked_at` | any field name | field where it is storing the time of beginning a lock of a document, must be of type `Time` |
107
+ | lock_timeout | `5` | | within this time (in seconds) a document is considered as locked |
108
+ | locker_write_concern | `{ w: 1 }` | see [MongoDB Write Concern](https://docs.mongodb.com/manual/reference/write-concern/#write-concern-specification)| a write concern only used for lock and unlock operations |
109
+ | maximum_backoff | `60.0` | | the highest timeout (in seconds) between retires to lock a document, reaching that value `#with_lock` method raises `Mongoid::Locker::Errors::DocumentCouldNotGetLock` |
110
+ | backoff_algorithm | `:exponential_backoff` | `:locked_at_backoff` or [custom algorithm](#custom-backoff_algorithm-and-locking_name_generator) | algorithm used for timeout calculating between retries to lock a document|
111
+ | locking_name_generator | `:secure_locking_name` | [custom generator](#custom-backoff_algorithm-and-locking_name_generator) | generator used to generate unique name of a lock |
112
+
113
+ For instances of a class where `Mongoid::Locker` is included, all parameters of a class are available for reading.
114
+ ```ruby
115
+ document.lock_timeout
116
+ #=> 5
117
+ ```
118
+
119
+ ### Custom :backoff_algorithm and :locking_name_generator
120
+ A method which is defined in `Mongoid::Locker` are available in a class where it is included.
121
+
122
+ Method `#with_lock` passes to the methods a document to which apply `#with_lock` and a hash of options. The hash may look like this:
123
+ ```ruby
124
+ { retries: Infinity, reload: true, attempt: 0, locking_name: "71c1ccd4-72d9-4a83-bbed-adf65803bd5d" }
125
+ ```
126
+
127
+ A custom backoff algorithmoff **must return** a value more or equal `maximum_backoff` value to force `#with_lock` quit trying to lock a document, otherwise `#with_lock` will be trying to lock a document `INFINITY` times.
128
+ ```ruby
129
+ Mongoid::Locker.configure do |config|
130
+ config.backoff_algorithm = :custom_backoff
131
+ end
132
+
133
+ module Mongoid
134
+ module Locker
135
+ def self.custom_backoff(doc, _opts)
136
+ rand > 0.5 ? 5 : doc.maximum_backoff
137
+ end
138
+ end
103
139
  end
104
140
  ```
105
141
 
142
+ A custom locking name generator **must return** a string to secure uniqueness name of locking.
143
+ ```ruby
144
+ class User
145
+ include Mongoid::Document
146
+ include Mongoid::Locker
147
+
148
+ locker locking_name_generator: :custom_locking_name
149
+
150
+ field :locker_locking_name, type: String
151
+ field :locker_locked_at, type: Time
152
+
153
+ def self.custom_locking_name(_doc, _opts)
154
+ SecureRandom.uuid
155
+ end
156
+ ```
157
+
106
158
  ## Copyright & License
107
159
 
108
- Copyright (c) 2012-2018 Aidan Feldman & Contributors
160
+ Copyright (c) 2012-2019 Aidan Feldman & Contributors
109
161
 
110
162
  MIT License, see [LICENSE](LICENSE.txt) for more information.