pg_advisory_locker 1.0.2 → 1.1.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.
- data/.travis.yml +15 -0
- data/LICENSE +1 -1
- data/README.md +61 -0
- data/lib/pg_advisory_locker/pg_advisory_locker.rb +75 -8
- data/lib/pg_advisory_locker/version.rb +1 -1
- data/pg_advisory_locker.gemspec +1 -1
- metadata +4 -3
- data/README +0 -47
data/.travis.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 1.9.3
|
4
|
+
bundler_args: --without staging development deploy
|
5
|
+
before_install:
|
6
|
+
before_script: cp spec/dummy/config/database-sample.yml spec/dummy/config/database.yml; cd spec/dummy; bundle exec rake db:create;
|
7
|
+
script: rspec spec
|
8
|
+
branches:
|
9
|
+
only:
|
10
|
+
- master
|
11
|
+
- production
|
12
|
+
notifications:
|
13
|
+
email:
|
14
|
+
- dev-fma@fiksu.com
|
15
|
+
|
data/LICENSE
CHANGED
data/README.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
pg_advisory_locker
|
2
|
+
==================
|
3
|
+
|
4
|
+
Helper for calling PostgreSQL functions: pg_advisory_lock,
|
5
|
+
pg_advisory_try_lock, and pg_advisory_unlock.
|
6
|
+
|
7
|
+
Examples
|
8
|
+
========
|
9
|
+
|
10
|
+
Basic example of passing a block to the locker
|
11
|
+
|
12
|
+
```
|
13
|
+
class Foo < ActiveRecord::Base
|
14
|
+
include PgAdvisoryLocker
|
15
|
+
|
16
|
+
def self.lock_for_whatever(&block)
|
17
|
+
return lock_record(0, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.do_something
|
21
|
+
lock_for_whatever do
|
22
|
+
# do something here
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
Advisory lock on id:
|
29
|
+
|
30
|
+
```
|
31
|
+
class Foo < ActiveRecord::Base
|
32
|
+
include PgAdvisoryLocker
|
33
|
+
|
34
|
+
def lock_for_whatever
|
35
|
+
return advisory_lock
|
36
|
+
end
|
37
|
+
|
38
|
+
def unlock_for_whatever
|
39
|
+
return advisory_unlock
|
40
|
+
end
|
41
|
+
|
42
|
+
def do_something
|
43
|
+
lock_for_whatever
|
44
|
+
begin
|
45
|
+
# do something
|
46
|
+
ensure
|
47
|
+
unlock_for_whatever
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
Generic locking:
|
53
|
+
```
|
54
|
+
class Foo < ActiveRecord::Base
|
55
|
+
include PgAdvisoryLocker
|
56
|
+
end
|
57
|
+
|
58
|
+
Foo.pg_advisory_lock(0, 0) do
|
59
|
+
# do something
|
60
|
+
end
|
61
|
+
```
|
@@ -3,19 +3,40 @@ module PgAdvisoryLocker
|
|
3
3
|
base.extend(ClassMethods)
|
4
4
|
end
|
5
5
|
|
6
|
+
# advisory lock this row associated identified by model#id
|
7
|
+
#
|
8
|
+
# blocks until advisory lock is release
|
9
|
+
# acquires lock on return
|
10
|
+
#
|
11
|
+
# if block is passed in, lock/unlock around the block
|
6
12
|
def advisory_lock(&block)
|
7
13
|
return self.class.lock_record(id, &block)
|
8
14
|
end
|
9
15
|
|
16
|
+
# advisory try lock this row associated identified by model#id
|
17
|
+
#
|
18
|
+
# if lock is acquired, acquires lock and returns true
|
19
|
+
# if lock is currently acquired, returns false
|
20
|
+
# never blocks
|
21
|
+
#
|
22
|
+
# if block is passed in, lock/unlock around the block
|
23
|
+
# executing block only if lock is acquired
|
10
24
|
def advisory_try_lock(&block)
|
11
25
|
return self.class.try_lock_record(id, &block)
|
12
26
|
end
|
13
27
|
|
28
|
+
# advisory unlock this row associated identified by model#id
|
29
|
+
#
|
30
|
+
# on return releases lock
|
14
31
|
def advisory_unlock
|
15
32
|
self.class.unlock_record(id)
|
16
33
|
end
|
17
34
|
|
18
35
|
module ClassMethods
|
36
|
+
# table_oid is good unique identifier value for the table
|
37
|
+
# We could use a has of the name if the thought there would
|
38
|
+
# be no collisions
|
39
|
+
# The OID is always unique, so we use it
|
19
40
|
def table_oid
|
20
41
|
if @table_oid.nil?
|
21
42
|
sql_table_components = table_name.split('.')
|
@@ -37,39 +58,85 @@ module PgAdvisoryLocker
|
|
37
58
|
return @table_oid
|
38
59
|
end
|
39
60
|
|
40
|
-
|
61
|
+
# advisory lock for this model, with key2 as argument
|
62
|
+
# blocks until advisory lock is release
|
63
|
+
# acquires lock on return
|
64
|
+
#
|
65
|
+
# if block is passed in, lock/unlock around the block
|
66
|
+
def lock_record(key2, &block)
|
67
|
+
return pg_advisory_lock(table_oid, key2, &block)
|
68
|
+
end
|
69
|
+
|
70
|
+
# advisory try lock for this model, with key2 as argument
|
71
|
+
#
|
72
|
+
# if lock is acquired, acquires lock and returns true
|
73
|
+
# if lock is currently acquired, returns false
|
74
|
+
# never blocks
|
75
|
+
#
|
76
|
+
# if block is passed in, lock/unlock around the block
|
77
|
+
# executing block only if lock is acquired
|
78
|
+
def try_lock_record(key2, &block)
|
79
|
+
return pg_try_advisory_lock(table_oid, key2, &block)
|
80
|
+
end
|
81
|
+
|
82
|
+
# advisory unlock for this model, with key2 as argument
|
83
|
+
# on return releases lock
|
84
|
+
def unlock_record(key2)
|
85
|
+
return pg_advisory_unlock(table_oid, key2)
|
86
|
+
end
|
87
|
+
|
88
|
+
# pg_advisory_lock - direct access to postgres pg_advisory_lock function
|
89
|
+
# key1: int
|
90
|
+
# key2: int
|
91
|
+
# if block is passed in, lock/unlock around the block
|
92
|
+
def pg_advisory_lock(key1, key2, &block)
|
41
93
|
locked = uncached do
|
42
|
-
find_by_sql(["select pg_advisory_lock(?, ?)",
|
94
|
+
find_by_sql(["select pg_advisory_lock(?, ?)", key1, key2]).first.pg_advisory_lock == "t"
|
43
95
|
end
|
44
96
|
if block.present?
|
45
97
|
begin
|
46
98
|
return block.call
|
47
99
|
ensure
|
48
|
-
|
100
|
+
pg_advisory_unlock(key1, key2)
|
49
101
|
end
|
50
102
|
end
|
51
103
|
return locked
|
52
104
|
end
|
53
105
|
|
54
|
-
|
106
|
+
# pg_try_advisory_lock - direct access to postgres pg_try_advisory_lock function
|
107
|
+
# key1: int
|
108
|
+
# key2: int
|
109
|
+
#
|
110
|
+
# if lock is acquired, acquires lock and returns true
|
111
|
+
# if lock is currently acquired, returns false
|
112
|
+
# never blocks
|
113
|
+
#
|
114
|
+
# if block is passed in, lock/unlock around the block
|
115
|
+
# executing block only if lock is acquired
|
116
|
+
def pg_try_advisory_lock(key1, key2, &block)
|
55
117
|
locked = uncached do
|
56
|
-
find_by_sql(["select pg_try_advisory_lock(?, ?)",
|
118
|
+
find_by_sql(["select pg_try_advisory_lock(?, ?)", key1, key2]).first.pg_try_advisory_lock == "t"
|
57
119
|
end
|
58
120
|
if locked
|
59
121
|
if block.present?
|
60
122
|
begin
|
61
123
|
block.call
|
62
124
|
ensure
|
63
|
-
|
125
|
+
pg_advisory_unlock(key1, key2)
|
64
126
|
end
|
65
127
|
end
|
66
128
|
end
|
67
129
|
return locked
|
68
130
|
end
|
69
131
|
|
70
|
-
|
132
|
+
# pg_advisory_unlock - direct access to postgres pg_advisory_unlock function
|
133
|
+
# key1: int
|
134
|
+
# key2: int
|
135
|
+
#
|
136
|
+
# on return releases lock
|
137
|
+
def pg_advisory_unlock(key1, key2)
|
71
138
|
unlocked = uncached do
|
72
|
-
find_by_sql(["select pg_advisory_unlock(?, ?)",
|
139
|
+
find_by_sql(["select pg_advisory_unlock(?, ?)", key1, key2]).first.pg_advisory_unlock == "t"
|
73
140
|
end
|
74
141
|
return unlocked
|
75
142
|
end
|
data/pg_advisory_locker.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.name = 'pg_advisory_locker'
|
8
8
|
s.version = PgAdvisoryLocker::VERSION
|
9
9
|
s.license = 'New BSD License'
|
10
|
-
s.date = '
|
10
|
+
s.date = '2013-04-26'
|
11
11
|
s.summary = "Helper for calling PostgreSQL pg_advisory_lock, pg_advisory_try_lock, and pg_advisory_unlock."
|
12
12
|
s.description = "This gem provides a module that, when included in your ActiveRecord model, provides methods to acquire and release advisory locks for PostgreSQL connections."
|
13
13
|
s.authors = ["Keith Gabryelski"]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_advisory_locker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-04-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: pg
|
@@ -68,10 +68,11 @@ extra_rdoc_files: []
|
|
68
68
|
files:
|
69
69
|
- .gitignore
|
70
70
|
- .rspec
|
71
|
+
- .travis.yml
|
71
72
|
- Gemfile
|
72
73
|
- Gemfile.lock
|
73
74
|
- LICENSE
|
74
|
-
- README
|
75
|
+
- README.md
|
75
76
|
- Rakefile
|
76
77
|
- lib/pg_advisory_locker.rb
|
77
78
|
- lib/pg_advisory_locker/pg_advisory_locker.rb
|
data/README
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
pg_advisory_locker
|
2
|
-
==================
|
3
|
-
|
4
|
-
Helper for calling PostgreSQL functions: pg_advisory_lock,
|
5
|
-
pg_advisory_try_lock, and pg_advisory_unlock.
|
6
|
-
|
7
|
-
Examples
|
8
|
-
========
|
9
|
-
|
10
|
-
Basic example of passing a block to the locker
|
11
|
-
|
12
|
-
class Foo < ActiveRecord::Base
|
13
|
-
include PgAdvisoryLocker
|
14
|
-
|
15
|
-
def self.lock_for_whatever(&block)
|
16
|
-
return lock_record(0, &block)
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.do_something
|
20
|
-
lock_for_whatever do
|
21
|
-
# do something here
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
Advisory lock on id:
|
27
|
-
|
28
|
-
class Foo < ActiveRecord::Base
|
29
|
-
include PgAdvisoryLocker
|
30
|
-
|
31
|
-
def lock_for_whatever
|
32
|
-
return advisory_lock
|
33
|
-
end
|
34
|
-
|
35
|
-
def unlock_for_whatever
|
36
|
-
return advisory_unlock
|
37
|
-
end
|
38
|
-
|
39
|
-
def do_something
|
40
|
-
lock_for_whatever
|
41
|
-
begin
|
42
|
-
# do something
|
43
|
-
ensure
|
44
|
-
unlock_for_whatever
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|