lock-smith 0.0.6 → 0.0.8
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/dynamodb.rb +30 -51
- data/readme.md +6 -1
- metadata +1 -1
data/lib/locksmith/dynamodb.rb
CHANGED
@@ -1,68 +1,51 @@
|
|
1
1
|
require 'timeout'
|
2
2
|
require 'thread'
|
3
3
|
require 'locksmith/config'
|
4
|
-
require 'locksmith/log'
|
5
4
|
|
6
5
|
module Locksmith
|
7
6
|
module Dynamodb
|
8
7
|
extend self
|
9
|
-
|
10
|
-
MAX_LOCK_ATTEMPTS = 3
|
11
|
-
LOCK_TIMEOUT = 30
|
12
|
-
LOCK_TABLE = "Locks"
|
13
|
-
|
8
|
+
# s safe for threads. This module i
|
14
9
|
@dynamo_lock = Mutex.new
|
15
10
|
@table_lock = Mutex.new
|
16
11
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
attempts
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
write_lock(name, 0, new_rev)
|
30
|
-
log(:at => "lock-acquired", :lock => name, :rev => new_rev)
|
31
|
-
result = yield
|
32
|
-
release_lock(name, new_rev)
|
33
|
-
log(:at => "lock-released", :lock => name, :rev => new_rev)
|
34
|
-
return result
|
35
|
-
end
|
36
|
-
rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException
|
37
|
-
log(:at => "lock-not-acquired", :lock => name, :last_rev => last_rev, :new_rev => new_rev)
|
38
|
-
attempts += 1
|
39
|
-
rescue Timeout::Error
|
40
|
-
attempts += 1
|
41
|
-
release_lock(name, new_rev)
|
42
|
-
log(:at => "timeout-lock-released", :lock => name, :rev => new_rev)
|
12
|
+
LOCK_TABLE = "Locks"
|
13
|
+
|
14
|
+
def lock(name, opts={})
|
15
|
+
opts[:ttl] ||= 60
|
16
|
+
opts[:attempts] ||= 3
|
17
|
+
# Clean up expired locks. Does not grantee that we will
|
18
|
+
# be able to acquire the lock, just a nice thing to do for
|
19
|
+
# the other processes attempting to lock.
|
20
|
+
rm(name) if expired?(name, opts[:ttl])
|
21
|
+
if create(name, opts[:attempts])
|
22
|
+
begin Timeout::timeout(opts[:ttl]) {return(yield)}
|
23
|
+
ensure rm(name)
|
43
24
|
end
|
44
25
|
end
|
45
26
|
end
|
46
27
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
28
|
+
def create(name, attempts)
|
29
|
+
attempts.times do |i|
|
30
|
+
begin
|
31
|
+
locks.put({"Name" => name, "Created" => Time.now.to_i},
|
32
|
+
:unless_exists => "Name")
|
33
|
+
return(true)
|
34
|
+
rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException
|
35
|
+
return(false) if i == (attempts - 1)
|
36
|
+
end
|
37
|
+
end
|
55
38
|
end
|
56
39
|
|
57
|
-
def
|
58
|
-
locks.
|
40
|
+
def rm(name)
|
41
|
+
locks.at(name).delete
|
59
42
|
end
|
60
43
|
|
61
|
-
def
|
62
|
-
if locks.at(name).
|
63
|
-
|
64
|
-
|
65
|
-
|
44
|
+
def expired?(name, ttl)
|
45
|
+
if l = locks.at(name).attributes.to_h(:consistent_read => true)
|
46
|
+
if t = l["Created"]
|
47
|
+
t < (Time.now.to_i - ttl)
|
48
|
+
end
|
66
49
|
end
|
67
50
|
end
|
68
51
|
|
@@ -87,9 +70,5 @@ module Locksmith
|
|
87
70
|
end
|
88
71
|
end
|
89
72
|
|
90
|
-
def log(data, &blk)
|
91
|
-
Log.log({ns: "dynamo-lock"}.merge(data), &blk)
|
92
|
-
end
|
93
|
-
|
94
73
|
end
|
95
74
|
end
|
data/readme.md
CHANGED
@@ -14,7 +14,7 @@ A library of locking algorithms for a variety of data stores. Supported Data Sto
|
|
14
14
|
There is only 1 public method:
|
15
15
|
|
16
16
|
```
|
17
|
-
lock(name, &blk)
|
17
|
+
lock(name, opts, &blk)
|
18
18
|
```
|
19
19
|
|
20
20
|
Install using the gem. The gem does not depend on the data store drivers, you will need to install those for yourself.
|
@@ -39,6 +39,11 @@ Locksmith::Dynamodb.lock("my-resource") do
|
|
39
39
|
end
|
40
40
|
```
|
41
41
|
|
42
|
+
#### Options
|
43
|
+
|
44
|
+
* ttl - Sets TTL on the DynamoDB item & Wraps your block in a timeout. Be sure to handle `Timeout::Error`.
|
45
|
+
* attempts - Number of attempts to create DynamoDB item. Your code will only run once.
|
46
|
+
|
42
47
|
### PostgreSQL
|
43
48
|
|
44
49
|
Locksmith will use `pg_try_advisory_lock` to lock, no need for table creation.
|