db_lock 0.7 → 0.8.2

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: 3494b2768567c673a466817880e0d5d8170371b463b16e1d764c7e9a29819303
4
- data.tar.gz: 1129de916ae216947ab91383f34af010a63adccc996f12bfc9b5a1ba2b706785
3
+ metadata.gz: f59c12f3f279febb7c5350a2b4b6638d222bc50beeb038563a59afac4efa4328
4
+ data.tar.gz: 499be9d47073117184c99fdebf1f398eb2b50cb0aa5cd7e082fa55945033e263
5
5
  SHA512:
6
- metadata.gz: b8194e0c7d778d734503fe0716cfc2dca17524961538cae5b5267ac7ba331f8d34752932970a70fa0b83e2398ff9d8ff6bf6434acf9104437ee1d59a1e0cc7d9
7
- data.tar.gz: 2568337c2863e5f76e1c7f38a672885d73f8936ec9b1e45981da3ac964900269b66dc379dc737a68fec24dc42c79f05ff404357c90981a194be3fa5caeea5b4e
6
+ metadata.gz: c447141d577b1baa3fef43abd12ee20941603a0659b281514d58b6f797bfec611743c71f7a08b07d1a054417647313dca4847774b3314e2db21ca2f8779e084f
7
+ data.tar.gz: 941c56299b884aa698b6e9d1bbfa18ea83555dc77f2965a73b21cf6cf0f66a718ec68eb2c681a6ed6a13c0d428e896bce8e40ddef5ca49cc5a010cfafa43afd9
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # DBLock
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/db_lock.svg)](https://badge.fury.io/rb/db_lock)
4
+ [![Tests](https://github.com/mkon/db_lock/actions/workflows/test.yml/badge.svg)](https://github.com/mkon/db_lock/actions/workflows/test.yml)
5
+
3
6
  Gem to obtain and release manual db locks. This can be utilized for example to make sure that certain rake tasks do not run in parallel on the same database (for example when cron jobs run for too long or are accidentally started multiple times). Currently only supports:
4
7
 
5
8
  - MySQL
@@ -23,7 +26,7 @@ end
23
26
 
24
27
  Before the code block is executed, it will attempt to acquire a mysql db lock for X seconds (5 in this example). If this fails it will raise an `DBLock::AlreadyLocked` error. The lock is released after the block is executed, even if the block raised an error itself.
25
28
 
26
- The current implementation uses a class variable to store lock state so it is not thread save when using multiple threads to aquire/release locks.
29
+ The current implementation uses a class variable to store lock state so it is not thread-safe when using multiple threads to acquire/release locks.
27
30
 
28
31
  ## Smart lock name
29
32
 
@@ -35,13 +38,13 @@ If the lock name exceeds 64 characters, it will be replaced with a lock name of
35
38
 
36
39
  Bundle with the adapter you want to use, for example
37
40
 
38
- ```
39
- bundle --with mysql2
41
+ ```bash
42
+ $ bundle --with mysql
40
43
  ```
41
44
 
42
45
  Run rspec with the database url env variables set. It will only run the specs it can run and skip the others.
43
46
 
44
47
  For example
45
- ```
46
- MYSQL_URL=mysql2://root:dummy@localhost/test SQLSERVER_URL=sqlserver://root:dummy@localhost/test rspec
48
+ ```bash
49
+ $ MYSQL_URL=mysql2://root:dummy@localhost/test SQLSERVER_URL=sqlserver://root:dummy@localhost/test rspec
47
50
  ```
@@ -1,14 +1,14 @@
1
1
  module DBLock
2
2
  module Adapter
3
3
  class MYSQL < Base
4
- def lock(name, timeout=0)
5
- sql = sanitize_sql_array "SELECT GET_LOCK(?, ?)", name, timeout
4
+ def lock(name, timeout = 0)
5
+ sql = sanitize_sql_array 'SELECT GET_LOCK(?, ?)', name, timeout
6
6
  res = connection.select_one sql
7
7
  (res && res.values.first == 1)
8
8
  end
9
9
 
10
10
  def release(name)
11
- sql = sanitize_sql_array "SELECT RELEASE_LOCK(?)", name
11
+ sql = sanitize_sql_array 'SELECT RELEASE_LOCK(?)', name
12
12
  res = connection.select_one sql
13
13
  (res && res.values.first == 1)
14
14
  end
@@ -1,16 +1,22 @@
1
1
  module DBLock
2
2
  module Adapter
3
3
  class Sqlserver < Base
4
- def lock(name, timeout=0)
5
- connection.execute_procedure 'sp_getapplock', Resource: name, LockMode: 'Exclusive', LockOwner: 'Session', LockTimeout: (timeout*1000).to_i, DbPrincipal: 'public'
4
+ def lock(name, timeout = 0)
5
+ connection.execute_procedure 'sp_getapplock', Resource: name,
6
+ LockMode: 'Exclusive',
7
+ LockOwner: 'Session',
8
+ LockTimeout: (timeout * 1000).to_i,
9
+ DbPrincipal: 'public'
6
10
  lock = connection.raw_connection.return_code
7
- lock == 0
11
+ lock.zero?
8
12
  end
9
13
 
10
14
  def release(name)
11
- connection.execute_procedure 'sp_releaseapplock', Resource: name, LockOwner: 'Session', DbPrincipal: 'public'
15
+ connection.execute_procedure 'sp_releaseapplock', Resource: name,
16
+ LockOwner: 'Session',
17
+ DbPrincipal: 'public'
12
18
  lock = connection.raw_connection.return_code
13
- lock == 0
19
+ lock.zero?
14
20
  end
15
21
  end
16
22
  end
@@ -2,9 +2,9 @@ module DBLock
2
2
  module Adapter
3
3
  extend self
4
4
 
5
- autoload :Base, "db_lock/adapter/base"
6
- autoload :MYSQL, "db_lock/adapter/mysql"
7
- autoload :Sqlserver, "db_lock/adapter/sqlserver"
5
+ autoload :Base, 'db_lock/adapter/base'
6
+ autoload :MYSQL, 'db_lock/adapter/mysql'
7
+ autoload :Sqlserver, 'db_lock/adapter/sqlserver'
8
8
 
9
9
  delegate :lock, :release, to: :implementation
10
10
 
@@ -0,0 +1,51 @@
1
+ require 'digest/md5'
2
+
3
+ module DBLock
4
+ module Lock
5
+ extend self
6
+
7
+ # rubocop:disable Metrics/AbcSize
8
+ def get(name, timeout = 0)
9
+ timeout = timeout.to_f # catches nil
10
+ timeout = 0 if timeout.negative?
11
+
12
+ raise "Invalid lock name: #{name.inspect}" if name.empty?
13
+ raise AlreadyLocked, 'Already lock in progress' if locked?
14
+
15
+ name = generate_lock_name(name)
16
+
17
+ if Adapter.lock(name, timeout)
18
+ @locked = true
19
+ yield
20
+ else
21
+ raise AlreadyLocked, "Unable to obtain lock '#{name}' within #{timeout} seconds" unless locked?
22
+ end
23
+ ensure
24
+ Adapter.release(name) if locked?
25
+ @locked = false
26
+ end
27
+ # rubocop:enable Metrics/AbcSize
28
+
29
+ def locked?
30
+ @locked ||= false
31
+ end
32
+
33
+ private
34
+
35
+ def generate_lock_name(name)
36
+ name = "#{rails_app_name}.#{Rails.env}#{name}" if name[0] == '.' && defined? Rails
37
+ # reduce lock names of > 64 chars in size
38
+ # MySQL 5.7 only supports 64 chars max, there might be similar limitations elsewhere
39
+ name = "#{name.chars.first(15).join}-#{Digest::MD5.hexdigest(name)}-#{name.chars.last(15).join}" if name.length > 64
40
+ name
41
+ end
42
+
43
+ def rails_app_name
44
+ if Gem::Version.new(Rails.version) >= Gem::Version.new('6.0.0')
45
+ Rails.application.class.module_parent_name
46
+ else
47
+ Rails.application.class.parent_name
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,3 +1,3 @@
1
1
  module DBLock
2
- VERSION = "0.7"
2
+ VERSION = '0.8.2'.freeze
3
3
  end
data/lib/db_lock.rb CHANGED
@@ -3,7 +3,8 @@ require 'digest/md5'
3
3
  module DBLock
4
4
  extend self
5
5
 
6
- autoload :Adapter, "db_lock/adapter"
6
+ autoload :Adapter, 'db_lock/adapter'
7
+ autoload :Lock, 'db_lock/lock'
7
8
 
8
9
  class AlreadyLocked < StandardError; end
9
10
 
@@ -13,47 +14,4 @@ module DBLock
13
14
  # this must be an active record base object or subclass
14
15
  @db_handler || ActiveRecord::Base
15
16
  end
16
-
17
- module Lock
18
- extend self
19
-
20
- def get(name, timeout=0)
21
- timeout = timeout.to_f # catches nil
22
- timeout = 0 if timeout < 0
23
- raise "Invalid lock name: #{name.inspect}" if name.empty?
24
- raise AlreadyLocked.new("Already lock in progress") if locked?
25
-
26
- name = generate_lock_name(name)
27
-
28
- if Adapter.lock(name, timeout)
29
- @locked = true
30
- yield
31
- else
32
- raise AlreadyLocked.new("Unable to obtain lock '#{name}' within #{timeout} seconds") unless locked?
33
- end
34
- ensure
35
- if locked?
36
- Adapter.release(name)
37
- end
38
- @locked = false
39
- end
40
-
41
- def locked?
42
- @locked ||= false
43
- end
44
-
45
- private
46
-
47
- def generate_lock_name(name)
48
- if (name[0] == "." && defined? Rails)
49
- name = "#{Rails.application.class.parent_name}.#{Rails.env}#{name}"
50
- end
51
- # reduce lock names of > 64 chars in size
52
- # MySQL 5.7 only supports 64 chars max, there might be similar limitations elsewhere
53
- if name.length > 64
54
- name = "#{name.chars.first(15).join}-#{Digest::MD5.hexdigest(name)}-#{name.chars.last(15).join}"
55
- end
56
- name
57
- end
58
- end
59
17
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: db_lock
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.7'
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - mkon
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-30 00:00:00.000000000 Z
11
+ date: 2022-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,20 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '3.0'
19
+ version: '5.2'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '6'
22
+ version: '7.1'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '3.0'
29
+ version: '5.2'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '6'
32
+ version: '7.1'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rspec
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -44,8 +44,50 @@ dependencies:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
46
  version: '3.7'
47
- description: Obtain manual db locks to guard blocks of code from parallel execution.
48
- Currently only supports mysql and ms-sql-server.
47
+ - !ruby/object:Gem::Dependency
48
+ name: rubocop
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - '='
52
+ - !ruby/object:Gem::Version
53
+ version: 1.28.2
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '='
59
+ - !ruby/object:Gem::Version
60
+ version: 1.28.2
61
+ - !ruby/object:Gem::Dependency
62
+ name: rubocop-rspec
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - '='
66
+ - !ruby/object:Gem::Version
67
+ version: 2.10.0
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '='
73
+ - !ruby/object:Gem::Version
74
+ version: 2.10.0
75
+ - !ruby/object:Gem::Dependency
76
+ name: simplecov
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ description: Obtain manual db locks to guard blocks of code from parallel execution.Currently
90
+ only supports mysql and ms-sql-server.
49
91
  email:
50
92
  - konstantin@munteanu.de
51
93
  executables: []
@@ -54,21 +96,19 @@ extra_rdoc_files: []
54
96
  files:
55
97
  - MIT-LICENSE
56
98
  - README.md
57
- - config/database_mssql.yml
58
- - config/database_mssql_example.yml
59
- - config/database_mysql.yml
60
- - config/database_mysql_example.yml
61
99
  - lib/db_lock.rb
62
100
  - lib/db_lock/adapter.rb
63
101
  - lib/db_lock/adapter/base.rb
64
102
  - lib/db_lock/adapter/mysql.rb
65
103
  - lib/db_lock/adapter/sqlserver.rb
104
+ - lib/db_lock/lock.rb
66
105
  - lib/db_lock/version.rb
67
106
  homepage: https://github.com/mkon/db_lock
68
107
  licenses:
69
108
  - MIT
70
- metadata: {}
71
- post_install_message:
109
+ metadata:
110
+ rubygems_mfa_required: 'true'
111
+ post_install_message:
72
112
  rdoc_options: []
73
113
  require_paths:
74
114
  - lib
@@ -76,16 +116,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
76
116
  requirements:
77
117
  - - ">="
78
118
  - !ruby/object:Gem::Version
79
- version: '0'
119
+ version: '2.7'
120
+ - - "<"
121
+ - !ruby/object:Gem::Version
122
+ version: '3.1'
80
123
  required_rubygems_version: !ruby/object:Gem::Requirement
81
124
  requirements:
82
125
  - - ">="
83
126
  - !ruby/object:Gem::Version
84
127
  version: '0'
85
128
  requirements: []
86
- rubyforge_project:
87
- rubygems_version: 2.7.5
88
- signing_key:
129
+ rubygems_version: 3.2.15
130
+ signing_key:
89
131
  specification_version: 4
90
132
  summary: Obtain manual db/mysql locks
91
133
  test_files: []
@@ -1,17 +0,0 @@
1
- # rename/copy to database.yml and adjust to your local settings
2
-
3
- base: &base
4
- adapter: sqlserver
5
- host: 192.168.99.100
6
- port: 50012
7
- encoding: utf8
8
- reconnect: false
9
- pool: 5
10
- username: root
11
- password: dummy
12
-
13
- development:
14
- <<: *base
15
-
16
- test:
17
- <<: *base
@@ -1,17 +0,0 @@
1
- # rename/copy to database.yml and adjust to your local settings
2
-
3
- base: &base
4
- adapter: sqlserver
5
- host: 192.168.99.100
6
- port: 50012
7
- encoding: utf8
8
- reconnect: false
9
- pool: 5
10
- username: root
11
- password: dummy
12
-
13
- development:
14
- <<: *base
15
-
16
- test:
17
- <<: *base
@@ -1,14 +0,0 @@
1
- base: &base
2
- adapter: mysql2
3
- host: localhost
4
- encoding: utf8
5
- reconnect: false
6
- pool: 5
7
- username: root
8
- password: dummy
9
-
10
- development:
11
- <<: *base
12
-
13
- test:
14
- <<: *base
@@ -1,16 +0,0 @@
1
- # rename/copy to database.yml and adjust to your local settings
2
-
3
- base: &base
4
- adapter: mysql2
5
- host: localhost
6
- encoding: utf8
7
- reconnect: false
8
- pool: 5
9
- username: root
10
- password: dummy
11
-
12
- development:
13
- <<: *base
14
-
15
- test:
16
- <<: *base