lock-smith 0.0.9 → 1.0.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/lib/locksmith/config.rb +5 -0
- data/lib/locksmith/dynamodb.rb +16 -7
- data/lib/locksmith/pg.rb +35 -18
- data/readme.md +5 -13
- metadata +1 -2
data/lib/locksmith/config.rb
CHANGED
data/lib/locksmith/dynamodb.rb
CHANGED
@@ -9,8 +9,6 @@ module Locksmith
|
|
9
9
|
@dynamo_lock = Mutex.new
|
10
10
|
@table_lock = Mutex.new
|
11
11
|
|
12
|
-
LOCK_TABLE = "Locks"
|
13
|
-
|
14
12
|
def lock(name, opts={})
|
15
13
|
opts[:ttl] ||= 60
|
16
14
|
opts[:attempts] ||= 3
|
@@ -50,17 +48,20 @@ module Locksmith
|
|
50
48
|
end
|
51
49
|
|
52
50
|
def locks
|
53
|
-
table(
|
51
|
+
table(lock_table)
|
54
52
|
end
|
55
53
|
|
56
54
|
def table(name)
|
57
|
-
|
55
|
+
unless tables[name]
|
56
|
+
@table_lock.synchronize do
|
57
|
+
tables[name] = dynamo.tables[name].load_schema
|
58
|
+
end
|
59
|
+
end
|
60
|
+
tables[name].items
|
58
61
|
end
|
59
62
|
|
60
63
|
def tables
|
61
|
-
@tables ||=
|
62
|
-
map {|t| t.load_schema}.
|
63
|
-
reduce({}) {|h, t| h[t.name] = t; h}
|
64
|
+
@tables ||= {}
|
64
65
|
end
|
65
66
|
|
66
67
|
def dynamo
|
@@ -70,5 +71,13 @@ module Locksmith
|
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
74
|
+
def lock_table
|
75
|
+
@lock_table
|
76
|
+
end
|
77
|
+
|
78
|
+
def lock_table=(table_name)
|
79
|
+
@lock_table = table_name
|
80
|
+
end
|
81
|
+
|
73
82
|
end
|
74
83
|
end
|
data/lib/locksmith/pg.rb
CHANGED
@@ -1,31 +1,49 @@
|
|
1
1
|
require 'zlib'
|
2
2
|
require 'uri'
|
3
|
+
require 'timeout'
|
4
|
+
require 'locksmith/config'
|
5
|
+
|
3
6
|
module Locksmith
|
4
7
|
module Pg
|
5
|
-
|
6
|
-
BACKOFF = 0.5
|
8
|
+
extend self
|
7
9
|
|
8
|
-
def lock(name)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
def lock(name, opts={})
|
11
|
+
opts[:ttl] ||= 60
|
12
|
+
opts[:attempts] ||= 3
|
13
|
+
opts[:lspace] ||= (Config.pg_lock_space || -2147483648)
|
14
|
+
|
15
|
+
if create(name, opts)
|
16
|
+
begin Timeout::timeout(opts[:ttl]) {return(yield)}
|
17
|
+
ensure delete(name, opts)
|
15
18
|
end
|
16
|
-
return result
|
17
|
-
ensure
|
18
|
-
release_lock(i)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
22
|
+
def key(name)
|
23
|
+
i = Zlib.crc32(name)
|
24
|
+
# We need to wrap the value for postgres
|
25
|
+
if i > 2147483647
|
26
|
+
-(-(i) & 0xffffffff)
|
27
|
+
else
|
28
|
+
i
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def create(name, opts)
|
33
|
+
lock_args = [opts[:lspace], key(name)]
|
34
|
+
opts[:attempts].times.each do |i|
|
35
|
+
res = conn.exec("select pg_try_advisory_lock($1,$2)", lock_args)
|
36
|
+
if res[0]["pg_try_advisory_lock"] == "t"
|
37
|
+
return(true)
|
38
|
+
else
|
39
|
+
return(false) if i == (opts[:attempts] - 1)
|
40
|
+
end
|
41
|
+
end
|
25
42
|
end
|
26
43
|
|
27
|
-
def
|
28
|
-
|
44
|
+
def delete(name, opts)
|
45
|
+
lock_args = [opts[:lspace], key(name)]
|
46
|
+
conn.exec("select pg_advisory_unlock($1,$2)", lock_args)
|
29
47
|
end
|
30
48
|
|
31
49
|
def conn=(conn)
|
@@ -53,4 +71,3 @@ module Locksmith
|
|
53
71
|
|
54
72
|
end
|
55
73
|
end
|
56
|
-
|
data/readme.md
CHANGED
@@ -1,13 +1,9 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
**This software is beta quality. Check back later for production quality.**
|
1
|
+
# lock-smith
|
4
2
|
|
5
3
|
A library of locking algorithms for a variety of data stores. Supported Data Stores:
|
6
4
|
|
7
5
|
* DynamoDB
|
8
6
|
* PostgreSQL
|
9
|
-
* TODO: Doozerd
|
10
|
-
* TODO: Zookeeper
|
11
7
|
|
12
8
|
## Usage
|
13
9
|
|
@@ -58,20 +54,16 @@ Locksmith::Pg.lock("my-resource") do
|
|
58
54
|
end
|
59
55
|
```
|
60
56
|
|
61
|
-
|
57
|
+
#### Options
|
62
58
|
|
63
|
-
|
64
|
-
|
59
|
+
* lspace - This defines which lock space lock-smith will use. This is handy if you have multiple applications using advisory locks.
|
60
|
+
* ttl - Wraps your block in a timeout. Be sure to handle `Timeout::Error`.
|
61
|
+
* attempts - Number of attempts to try advisory lock. Your code will only run once.
|
65
62
|
|
66
63
|
## Hacking on Locksmith
|
67
64
|
|
68
65
|
There are still some Data Stores to implement, follow the pattern for PostgreSQLand DynamoDB and submit a pull request.
|
69
66
|
|
70
|
-
## Contributors
|
71
|
-
|
72
|
-
* Ryan Smith
|
73
|
-
* Blake Gentry
|
74
|
-
|
75
67
|
## License
|
76
68
|
|
77
69
|
Copyright (C) 2012 Ryan Smith
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lock-smith
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -48,4 +48,3 @@ signing_key:
|
|
48
48
|
specification_version: 3
|
49
49
|
summary: Locking is hard. Write it once.
|
50
50
|
test_files: []
|
51
|
-
has_rdoc:
|