Module: Locksmith::Dynamodb
Constant Summary collapse
- TTL =
60
- MAX_LOCK_ATTEMPTS =
3
- LOCK_TIMEOUT =
30
- LOCK_TABLE =
"Locks"
Instance Method Summary collapse
- #dynamo ⇒ Object
- #fetch_lock(name) ⇒ Object
- #lock(name) ⇒ Object
- #locks ⇒ Object
- #log(data, &blk) ⇒ Object
- #release_lock(name, rev) ⇒ Object
- #release_lock!(name) ⇒ Object
- #table(name) ⇒ Object
- #tables ⇒ Object
- #write_lock(name, rev, new_rev) ⇒ Object
Instance Method Details
#dynamo ⇒ Object
82 83 84 85 86 87 |
# File 'lib/locksmith/dynamodb.rb', line 82 def dynamo @dynamo_lock.synchronize do @db ||= AWS::DynamoDB.new(:access_key_id => Config.aws_id, :secret_access_key => Config.aws_secret) end end |
#fetch_lock(name) ⇒ Object
60 61 62 63 64 65 66 |
# File 'lib/locksmith/dynamodb.rb', line 60 def fetch_lock(name) if locks.at(name).exists?(consistent_read: true) locks[name].attributes.to_h(consistent_read: true) else locks.put(:Name => name, :Locked => 0).attributes.to_h(consistent_read: true) end end |
#lock(name) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/locksmith/dynamodb.rb', line 16 def lock(name) lock = fetch_lock(name) last_rev = (lock["Locked"] || 0).to_i new_rev = Time.now.to_i attempts = 0 while attempts < MAX_LOCK_ATTEMPTS begin Timeout::timeout(LOCK_TIMEOUT) do if last_rev != 0 && last_rev < (Time.now.to_i - TTL) log(:at => "lock-expired", :lock => name, :last_rev => last_rev) release_lock!(name) end write_lock(name, 0, new_rev) log(:at => "lock-acquired", :lock => name, :rev => new_rev) result = yield release_lock(name, new_rev) log(:at => "lock-released", :lock => name, :rev => new_rev) return result end rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException log(:at => "lock-not-acquired", :lock => name, :last_rev => last_rev, :new_rev => new_rev) attempts += 1 rescue Timeout::Error attempts += 1 release_lock(name, new_rev) log(:at => "timeout-lock-released", :lock => name, :rev => new_rev) end end end |
#locks ⇒ Object
68 69 70 |
# File 'lib/locksmith/dynamodb.rb', line 68 def locks table(LOCK_TABLE) end |
#log(data, &blk) ⇒ Object
89 90 91 |
# File 'lib/locksmith/dynamodb.rb', line 89 def log(data, &blk) Log.log({ns: "dynamo-lock"}.merge(data), &blk) end |
#release_lock(name, rev) ⇒ Object
51 52 53 54 |
# File 'lib/locksmith/dynamodb.rb', line 51 def release_lock(name, rev) locks.put({:Name => name, :Locked => 0}, :if => {:Locked => rev}) end |
#release_lock!(name) ⇒ Object
56 57 58 |
# File 'lib/locksmith/dynamodb.rb', line 56 def release_lock!(name) locks.put({:Name => name, :Locked => 0}) end |
#table(name) ⇒ Object
72 73 74 |
# File 'lib/locksmith/dynamodb.rb', line 72 def table(name) @table_lock.synchronize {tables[name].items} end |
#tables ⇒ Object
76 77 78 79 80 |
# File 'lib/locksmith/dynamodb.rb', line 76 def tables @tables ||= dynamo.tables. map {|t| t.load_schema}. reduce({}) {|h, t| h[t.name] = t; h} end |
#write_lock(name, rev, new_rev) ⇒ Object
46 47 48 49 |
# File 'lib/locksmith/dynamodb.rb', line 46 def write_lock(name, rev, new_rev) locks.put({:Name => name, :Locked => new_rev}, :if => {:Locked => rev}) end |