module Dynalock::Lock

Public Instance Methods

acquire_lock(context:, owner: lock_default_owner, table: "locks", expire_time: 10) click to toggle source
# File lib/dynalock/lock.rb, line 6
def acquire_lock(context:, owner: lock_default_owner, table: "locks", expire_time: 10)
  dynamodb_client.put_item(
    table_name: table,
    item: {
      id: context,
      lock_owner: owner,
      expires: Time.now.utc.to_i + expire_time
    },
    condition_expression: "attribute_not_exists(expires) OR expires < :expires",
    expression_attribute_values: {
      ":expires": Time.now.utc.to_i
    }
  )
  true
rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException
  return false
end
refresh_lock(context:, owner: lock_default_owner, table: "locks", expire_time: 10) click to toggle source
# File lib/dynalock/lock.rb, line 24
def refresh_lock(context:, owner: lock_default_owner, table: "locks", expire_time: 10)
  dynamodb_client.update_item({
    table_name: table,
    key: { id: context },
    update_expression: "SET expires = :expires",
    condition_expression: "attribute_exists(expires) AND expires > :now AND lock_owner = :owner",
    expression_attribute_values: {
      ":expires": Time.now.utc.to_i + expire_time,
      ":owner": owner,
      ":now": Time.now.utc.to_i
    },
  })
  true
rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException
  return false
end
with_lock(context:, owner: lock_default_owner, table: "locks") { || ... } click to toggle source
# File lib/dynalock/lock.rb, line 41
def with_lock(context:, owner: lock_default_owner, table: "locks")
  expire_time = 5

  result = acquire_lock(context: context, owner: owner, table: table, expire_time: expire_time)
  raise Locked.new if result == false

  thread = Thread.new {
    loop do
      refresh_lock(context: context, owner: owner, table: table, expire_time: expire_time)
      sleep(expire_time / 2.0)
    end
  }
  if block_given?
    return yield
  end
ensure
  thread.kill unless thread.nil?
end

Private Instance Methods

dynamodb_client() click to toggle source
# File lib/dynalock/lock.rb, line 66
def dynamodb_client
  Aws::DynamoDB::Client.new
end
lock_default_owner() click to toggle source
# File lib/dynalock/lock.rb, line 62
def lock_default_owner
  @lock_default_owner ||= "#{ENV["USER"]}@#{`hostname`.strip}"
end