lockless 0.1.1 → 0.2.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: 04eeee62146005a7c2f6f68e89ba5ad82763a9b80918d68e63a1c47fcd486839
4
- data.tar.gz: e2ae421f25787bbb0a52413710c67ae1d2c29279c0436eb1f08bafe1561b14b0
3
+ metadata.gz: b5cc6bb9658c48705098956a9caabc7c3f10cd99631dcd6b0fe776592f57cc9d
4
+ data.tar.gz: 48d0dc5d8709224b6481e6d5b6316487c66b82b735a88a77d370d783bcaa62fd
5
5
  SHA512:
6
- metadata.gz: 8ff5c03de7a60853770cb7ae0fa0d07a06faa7750bb46dee3826eea73e9679b171011831e8e39f57d01fac9694028942959f88febcda3d8b0c758535ffce22d1
7
- data.tar.gz: add5bb7893659aba38ec88c41a20b56bd2c532f1275db13a029c35aa1ef1874f48c9bf82f643f933fd4003d9f479637b561e4ff5579591db18b54f3b528df7e7
6
+ metadata.gz: a6580bfc5ac693248c355b82d6e6b9113c2772660ce0d7b2d9c31553a2da212d122cf0b757c93df78b7a985544f030b6bb66697e400f8857a749418a17ca16c0
7
+ data.tar.gz: 3a6da4c0530cbe62a28831aec86966953cecf54433fac6ccd75070ff659b4febb1db2b1b5232f521476fca6595fc0a36402bcf4e3a42be9ba980e578e2e4cfb7
@@ -1,4 +1,4 @@
1
- name: Ruby
1
+ name: RubyCI
2
2
 
3
3
  on: [push,pull_request]
4
4
 
data/.rspec_status CHANGED
@@ -1,7 +1,9 @@
1
1
  example_id | status | run_time |
2
2
  ------------------------------------------ | ------ | --------------- |
3
- ./spec/lockless/model_spec.rb[1:1] | passed | 0.01249 seconds |
4
- ./spec/lockless/model_spec.rb[1:2:1:1] | passed | 0.02708 seconds |
5
- ./spec/lockless/model_spec.rb[1:2:2:1:1] | passed | 0.00505 seconds |
6
- ./spec/lockless/model_spec.rb[1:2:2:1:2:1] | passed | 0.02621 seconds |
7
- ./spec/lockless/model_spec.rb[1:2:2:2:1] | passed | 0.00658 seconds |
3
+ ./spec/lockless/model_spec.rb[1:1] | passed | 0.01148 seconds |
4
+ ./spec/lockless/model_spec.rb[1:2:1:1] | passed | 0.02232 seconds |
5
+ ./spec/lockless/model_spec.rb[1:3:1:1] | passed | 0.00415 seconds |
6
+ ./spec/lockless/model_spec.rb[1:3:2:1:1] | passed | 0.005 seconds |
7
+ ./spec/lockless/model_spec.rb[1:3:2:1:2:1] | passed | 0.03027 seconds |
8
+ ./spec/lockless/model_spec.rb[1:3:2:2:1] | passed | 0.00563 seconds |
9
+ ./spec/lockless/model_spec.rb[1:3:2:2:2] | passed | 0.00243 seconds |
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Lockless
2
2
 
3
- Concurrently update records without locks.
3
+ [![Gem Version](https://badge.fury.io/rb/lockless.png)](https://badge.fury.io/rb/lockless)
4
+ [![CI Status](https://github.com/cianmce/lockless/actions/workflows/main.yml/badge.svg)](https://github.com/cianmce/lockless/actions)
4
5
 
5
6
  Allows for safe concurrent updates to a single record without the need for locks.
6
7
 
@@ -66,6 +67,8 @@ user2.name = "new name2"
66
67
 
67
68
  # Save user2 before saving user1
68
69
  user2.lockless_save! # => true
70
+
71
+ # user1 fails to save as it's been updated earlier by user2
69
72
  user1.lockless_save! # => false
70
73
 
71
74
  # when lockless_save doesn't work you can either ignored the update
@@ -75,6 +78,15 @@ user1.reload
75
78
  user1.name # => "new name2"
76
79
  user1.name = "new name3"
77
80
  user1.lockless_save! # => true
81
+ user1.reload.name # => "new name3"
82
+
83
+ user1.reload
84
+ user1.name = "new name1"
85
+ User.all.update_all(name: "new name4")
86
+
87
+ # user1 fails to save as it's been updated earlier in `update_all`
88
+ user1.lockless_save! # => false
89
+ user1.reload.name # => "new name4"
78
90
  ```
79
91
 
80
92
  ## Development
@@ -83,13 +95,26 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
83
95
 
84
96
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
85
97
 
86
- ### Run all specs + standardrb
98
+ ### Testing
99
+ #### Run all specs + standardrb
87
100
 
88
101
  ```sh
89
102
  bundle exec rake
90
103
  ```
91
104
 
92
- ### Run specs using guard
105
+ #### Run only standardrb
106
+
107
+ ```sh
108
+ bundle exec rake standard
109
+ ````
110
+
111
+ #### Apply standardrb auto fixes
112
+
113
+ ```sh
114
+ bundle exec rake standard:fix
115
+ ```
116
+
117
+ #### Run specs using guard
93
118
 
94
119
  ```sh
95
120
  bundle exec guard
@@ -111,6 +136,5 @@ Everyone interacting in the Lockless project's codebases, issue trackers, chat r
111
136
 
112
137
  ## TODO
113
138
 
114
- - [ ] Allow for custom lockless column name
115
139
  - [ ] Allow for custom primary key column name
116
140
  - [ ] Allow a boolean to be passed to allow for validation to be skipped like in `.save`
@@ -2,6 +2,11 @@
2
2
 
3
3
  module Lockless
4
4
  # Handles lockless saves
5
+
6
+ #
7
+ # Options:
8
+ #
9
+ # - :lockless_column - The columns used to track soft delete, defaults to `:lockless_uuid`.
5
10
  module Model
6
11
  extend ActiveSupport::Concern
7
12
 
@@ -10,6 +15,14 @@ module Lockless
10
15
  self.lockless_column = :lockless_uuid
11
16
 
12
17
  before_save :set_lockless_uuid
18
+
19
+ delegate :generate_uuid, :lockless_column, to: :class
20
+ end
21
+
22
+ class_methods do
23
+ def generate_uuid
24
+ SecureRandom.uuid
25
+ end
13
26
  end
14
27
 
15
28
  # Saves record if it has not be modified in the time after it was loaded from the database.
@@ -18,18 +31,18 @@ module Lockless
18
31
  # false is returned if record is outdated or invalid
19
32
  def lockless_save
20
33
  return false unless valid?
21
- old_lockless_uuid = lockless_uuid
34
+ old_lockless_uuid = public_send(lockless_column)
22
35
  return save if new_record?
23
36
 
24
37
  run_callbacks(:save) do |variable|
25
38
  new_attrs = changed.collect { |prop| [prop.to_sym, self[prop]] }.to_h
26
39
 
27
- update_count = self.class.where(id: id, lockless_uuid: old_lockless_uuid).update_all(new_attrs)
40
+ update_count = self.class.where(:id => id, lockless_column => old_lockless_uuid).update_all(new_attrs)
28
41
  if update_count == 1
29
42
  changes_applied
30
43
  true
31
44
  else
32
- self.lockless_uuid = old_lockless_uuid
45
+ public_send("#{lockless_column}=", old_lockless_uuid)
33
46
  false
34
47
  end
35
48
  end
@@ -49,7 +62,7 @@ module Lockless
49
62
  private
50
63
 
51
64
  def set_lockless_uuid
52
- self.lockless_uuid = SecureRandom.uuid
65
+ public_send("#{lockless_column}=", generate_uuid)
53
66
  end
54
67
  end
55
68
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lockless
4
+ module Relation
5
+ def update_all(updates)
6
+ if model.method_defined?(:lockless_column) && updates[model.lockless_column].blank?
7
+ updates[model.lockless_column] = model.generate_uuid
8
+ end
9
+
10
+ super(updates)
11
+ end
12
+ end
13
+ end
14
+
15
+ ActiveRecord::Relation.prepend(Lockless::Relation)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lockless
4
- VERSION = "0.1.1"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/lockless.rb CHANGED
@@ -4,3 +4,4 @@ require "active_record"
4
4
 
5
5
  require "lockless/version"
6
6
  require "lockless/model"
7
+ require "lockless/relation"
data/lockless.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = "Allows for safe concurrent updates to a single record without the need for locks."
13
13
  spec.homepage = "https://github.com/cianmce/lockless"
14
14
  spec.license = "MIT"
15
- spec.required_ruby_version = ">= 2.3.0"
15
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
16
16
 
17
17
  spec.metadata["homepage_uri"] = spec.homepage
18
18
  spec.metadata["source_code_uri"] = spec.homepage
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lockless
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cian McElhinney
@@ -215,6 +215,7 @@ files:
215
215
  - bin/setup
216
216
  - lib/lockless.rb
217
217
  - lib/lockless/model.rb
218
+ - lib/lockless/relation.rb
218
219
  - lib/lockless/version.rb
219
220
  - lockless.gemspec
220
221
  homepage: https://github.com/cianmce/lockless